Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Am I going crazy or is Math.Pow broken?

I used the base converter from here and changed it to work with ulong values, but when converting large numbers, specifically numbers higher than 16677181699666568 it was returning incorrect values. I started looking into this and discovered that Math.Pow(3, 34) returns the value 16677181699666568, when actually 3^34 is 16677181699666569. This therefore throws a spanner in the works for me. I assume this is just an issue with double precision within the Pow method? Is my easiest fix just to create my own Pow that takes ulong values?

If so, what's the quickest way to do Pow? I assume there's something faster than a for loop with multiplication each time.

like image 245
Will Calderwood Avatar asked Dec 02 '22 03:12

Will Calderwood


2 Answers

You can use BigInteger.Pow. Or use my power method for long.

like image 140
Yuriy Faktorovich Avatar answered Dec 03 '22 18:12

Yuriy Faktorovich


The problem is that Math.Pow returns a double, and the closest double value to 16677181699666569 is 16677181699666568.

So without getting Math.Pow involved:

long accurate = 16677181699666569;
double closestDouble = accurate;
// See http://pobox.com/~skeet/csharp/DoubleConverter.cs
Console.WriteLine(DoubleConverter.ToExactString(closestDouble));

That prints 16677181699666568.

In other words whatever Math.Pow does internally, it can't return a result that's more accurate than the one you're getting.

As others have said, BigInteger.Pow is your friend if you're using .NET 4.

like image 38
Jon Skeet Avatar answered Dec 03 '22 19:12

Jon Skeet