如何在Java中对BigDecimal进行分数处理? [英] How to do a fractional power on BigDecimal in Java?
问题描述
在我的小项目中,我需要做一些像Math.pow(7777.66,5555.44)这样的东西只有非常大的数字。我遇到了一些解决方案:
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:
- 使用双倍 - 但数字太大
- 使用BigDecimal.pow但不支持分数
- 使用X ^(A + B)= X ^ A * X ^ B公式(B是第二个数字的余数),但是不支持大X或大A,因为我仍然转换为双
- 使用某种泰勒系列算法或类似的东西 - 我不是很擅长数学所以这一个是我的最后一个选项,如果我找不到任何解决方案(某些库或(A + B)^(C + D)的公式)。
- 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。
我发现了一些名为ApFloat的图书馆声称大约是这样做的,但我得到的结果非常接近甚至8 ^ 2给了我60 ...
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...
推荐答案
1.7976931348623157E308(Double.MAX_VALUE)下的参数解决方案,但支持数字为MILLIONS的结果:
The solution for arguments under 1.7976931348623157E308 (Double.MAX_VALUE) but supporting results with MILLIONS of digits:
由于double支持数字高达MAX_VALUE(例如,100!in double看起来像这样:9.332621544394415E157),使用BigDecimal.doubleValue()没有问题。但你不应该只做Math.pow(double,double),因为如果结果大于MAX_VALUE,你将获得无穷大。 SO:使用公式X ^(A + B)= X ^ A * X ^ B将计算分离为两个幂,使用BigDecimal.pow,使用Math将小(第二个参数的其余部分)分开。战争,然后繁殖。 X将被复制到DOUBLE - 确保它不大于MAX_VALUE,A将是INT(最大值2147483647但BigDecimal.pow不支持超过10亿的整数),B将是double,总是小于1。这样你可以执行以下操作(忽略我的私有常量等):
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):
int signOf2 = n2.signum();
try {
// 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
n2 = n2.multiply(new BigDecimal(signOf2)); // n2 is now positive
BigDecimal remainderOf2 = n2.remainder(BigDecimal.ONE);
BigDecimal n2IntPart = n2.subtract(remainderOf2);
// Calculate big part of the power using context -
// bigger range and performance but lower accuracy
BigDecimal intPow = n1.pow(n2IntPart.intValueExact(),
CalculatorConstants.DEFAULT_CONTEXT);
BigDecimal doublePow =
new BigDecimal(Math.pow(dn1, remainderOf2.doubleValue()));
result = intPow.multiply(doublePow);
} catch (Exception e) {
if (e instanceof CalculatorException)
throw (CalculatorException) e;
throw new CalculatorException(
CalculatorConstants.Errors.UNSUPPORTED_NUMBER_ +
"power!");
}
// Fix negative power
if (signOf2 == -1)
result = BigDecimal.ONE.divide(result, CalculatorConstants.BIG_SCALE,
RoundingMode.HALF_UP);
结果示例:
50!^10! = 12.50911317862076252364259*10^233996181
50!^0.06 = 7395.788659356498101260513
这篇关于如何在Java中对BigDecimal进行分数处理?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!