views:

49

answers:

2

In my little project I need to do something like Math.pow(7777.66, 5555.44) only with VERY big numbers. I came across a few solutions: - Use double - but the numbers are too big - Use BigDecimal.pow but no support for fractional - Use the X^(A+B)=X^A*X^B formula (B is the remainder of the second num), but again no support for big X or big A because I still convert to double - Use some kind of Taylor series algorithm or something like that - I'm not very good at math so this one is my last option if I don't find any solutions (some libraries or a formula for (A+B)^(C+D)). Anyone knows of a library or an easy solution? I figured that many people deal with the same problem...

p.s. I found some library called ApFloat that claims to do it approximately, but the results I got were so approximate that even 8^2 gave me 60...

A: 

Exponents = logarithms.

Take a look at http://stackoverflow.com/questions/739532/logarithm-of-a-bigdecimal

Matthew Flynn
Eh? They are certainly not synonyms if that is what you are saying...
mattburns
+1  A: 

The solution for arguments under 1.7976931348623157E308 (Double.MAX_VALUE) but supporting results with MILLIONS of digits:

Since double supports numbers up to MAX_VALUE (for example, 100! in double looks like this: 9.332621544394415E157), there is no problem to use BigDecimal.doubleValue(). But you shouldn't just do Math.pow(double, double) because if the result is bigger than MAX_VALUE you will just get infinity. SO: use the formula X^(A+B)=X^A*X^B to separate the calculation to TWO powers, the big, using BigDecimal.pow, and the small (remainder of the 2nd argument), using Math.pow, then multiply. X will be copied to DOUBLE - make sure it's not bigger than MAX_VALUE, A will be INT (maximum 2147483647 but the BigDecimal.pow doesn't support integers more than a billion anyway), and B will be double, always less than 1. This way you can do the following (ignore my private constants etc):

// Perform X^(A+B)=X^A*X^B (B = remainder)
double dn1 = n1.doubleValue();
// Compare the same row of digits according to context
if (!CalculatorUtils.isEqual(n1, dn1))
    throw new Exception(); // Cannot convert n1 to double
BigDecimal remainderOf2 = n2.remainder(BigDecimal.ONE, CalculatorConstants.DEFAULT_CONTEXT);
BigDecimal n2IntPart = n2.subtract(remainderOf2, CalculatorConstants.DEFAULT_CONTEXT);
BigDecimal intPow = n1.pow(n2IntPart.intValueExact(), CalculatorConstants.DEFAULT_CONTEXT);
BigDecimal doublePow = new BigDecimal(Math.pow(dn1, remainderOf2.doubleValue()));
result = intPow.multiply(doublePow, CalculatorConstants.DEFAULT_CONTEXT);

Results examples:

50!^10! = 12.50911317862076252364259*10^233996181

50!^0.06 = 7395.788659356498101260513
Gene