如何在Java的BigDecimal上发挥分数的力量?
-
01-10-2019 - |
题
在我的小项目中,我需要做诸如Math.pow(7777.66,5555.44)之类的事情,只有很大的数字。我遇到了一些解决方案:
- 使用双 - 但是数字太大
- 使用bigdecimal.pow,但不支持分数
- 使用x^(a+b)= x^a*x^b公式(b是第二个数字的其余部分),但再次不支持大x或大a,因为我仍然转换为double
- 使用某种泰勒系列算法或类似的东西 - 我不太擅长数学,所以如果我找不到任何解决方案(某些库或公式(a+b)^(c),这是我的最后选择。 +d))。
有人知道图书馆还是简单的解决方案?我认为很多人处理同样的问题...
PS我发现了一些名为Apfloat的库,声称可以大约这样做,但是我得到的结果近似,甚至8^2给了我60 ...
解决方案
根据1.7976931348623157E308(double.max_value)的参数解决方案,但具有数百万个数字的支持结果:
由于Double支持数字到MAX_VALUE(例如,100!双看起来像这样:9.3326215444394415E157),因此使用BigDecimal.double.double.double.double.double.double.double.double.double.double.double.double.double.double.double.double.double.double.double.double.double.double.double.double.double.double.double.double.double.double.double.double.double.double.double.double.double.double.double.double()。但是您不应该只是做数学。要做(双重,double),因为如果结果大于max_value,则只会获得无穷大。因此:使用公式x^(a+b)= x^a*x^b将计算与使用bigdecimal.pow和小(第二个参数的其余部分)的两个幂分开,并使用数学分开计算。 POW,然后繁殖。 X将被复制为double-确保它不大于max_value,a将是int(最多2147483647,但bigdecimal.pow不得支持整数超过10亿美元),并且b将翻倍,始终小于1。这样,您可以执行以下操作(忽略我的私有常数等):
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
其他提示
指数=对数。
看一眼 巨大的对数