I tried to use BigInteger.Pow
method to calculate something like 10^12345.987654321 but this method only accept integer number as exponent like this:
BigInteger.Pow(BigInteger x, int y)
so how can I use double number as exponent in above method?
There's no arbitrary precision large number support in C#, so this cannot be done directly. There are some alternatives (such as looking for a 3rd party library), or you can try something like the code below - if the base is small enough, like in your case.
public class StackOverflow_11179289
{
public static void Test()
{
int @base = 10;
double exp = 12345.123;
int intExp = (int)Math.Floor(exp);
double fracExp = exp - intExp;
BigInteger temp = BigInteger.Pow(@base, intExp);
double temp2 = Math.Pow(@base, fracExp);
int fractionBitsForDouble = 52;
for (int i = 0; i < fractionBitsForDouble; i++)
{
temp = BigInteger.Divide(temp, 2);
temp2 *= 2;
}
BigInteger result = BigInteger.Multiply(temp, (BigInteger)temp2);
Console.WriteLine(result);
}
}
The idea is to use big integer math to compute the power of the integer part of the exponent, then use double (64-bit floating point) math to compute the power of the fraction part. Then, using the fact that
a ^ (int + frac) = a ^ int * a ^ frac
we can combine the two values into a single big integer. But simply converting the double value to a BigInteger would lose a lot of its precision, so we first "shift" the precision onto the bigInteger (using the loop above, and the fact that the double
type uses 52 bits for the precision), then multiplying the result.
Notice that the result is an approximation, if you want a more precise number, you'll need a library that does arbitrary precision floating point math.
Update: If the base / exponent are small enough that the power would be in the range of double
, we can simply do what Sebastian Piu suggested (new BigInteger(Math.Pow((double)@base, exp))
)
I like carlosfigueira's answer, but of course the result of his method can only be correct on the first (most significant) 15-17 digits, because a System.Double
is used as a multiplier eventually.
It is interesting to note that there does exist a method BigInteger.Log
that performs the "inverse" operation. So if you want to calculate Pow(7, 123456.78)
you could, in theory, search all BigInteger
numbers x
to find one number such that BigInteger.Log(x, 7)
is equal to 123456.78
or closer to 123456.78
than any other x
of type BigInteger
.
Of course the logarithm function is increasing, so your search can use some kind of "binary search" (bisection search). Our answer lies between Pow(7, 123456)
and Pow(7, 123457)
which can both be calculated exactly.
Skip the rest if you want
Now, how can we predict in advance if there are more than one integer whose logarithm is 123456.78
, up to the precision of System.Double
, or if there is in fact no integer whose logarithm hits that specific Double
(the precise result of an ideal Pow
function being an irrational number)? In our example, there will be very many integers giving the same Double
123456.78
because the factor m = Pow(7, epsilon)
(where epsilon
is the smallest positive number such that 123456.78 + epilon
has a representation as a Double
different from the representation of 123456.78
itself) is big enough that there will be very many integers between the true answer and the true answer multiplied by m
.
Remember from calculus that the derivative of the mathemtical function x → Pow(7, x)
is x → Log(7)*Pow(7, x)
, so the slope of the graph of the exponential function in question will be Log(7)*Pow(7, 123456.78)
. This number multiplied by the above epsilon
is still much much greater than one, so there are many integers satisfying our need.
Actually, I think carlosfigueira's method will give a "correct" answer x
in the sense that Log(x, 7)
has the same representation as a Double
as 123456.78
has. But has anyone tried it? :-)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With