如何在Java中的BigDecimal上做一个分数幂?

2022-09-01 16:07:36

在我的小项目中,我需要做一些类似的事情,只有非常大的数字。我遇到了一些解决方案:Math.pow(7777.66, 5555.44)

  • 使用 - 但数字太大double
  • 使用但不支持分数BigDecimal.pow
  • 使用公式(是第二个数字的其余部分),但同样不支持大或大,因为我仍然转换为双精度X^(A+B)=X^A*X^BBXA
  • 使用某种泰勒级数算法或类似的东西 - 我不是很擅长数学,所以如果我找不到任何解决方案(一些库或公式),这是我的最后一个选择。(A+B)^(C+D)

有谁知道一个库或一个简单的解决方案?我想很多人都在处理同样的问题...

p.s. 我发现了一个名为ApFloat的库,声称大约可以做到这一点,但我得到的结果非常近似,甚至给了我......8^260


答案 1

1.7976931348623157E308 (Double.MAX_VALUE) 下的参数的解决方案,但支持数百万位数字的结果:

由于 double 支持最多 MAX_VALUE 的数字(例如,double 中的 100!如下所示:9.332621544394415E157),因此使用 BigDecimal.doubleValue() 没有问题。但是你不应该只做Math.pow(double,double),因为如果结果大于MAX_VALUE你只会得到无穷大。SO:使用公式 X^(A+B)=X^A*X^B 将计算分为两个幂,大,使用 BigDecimal.pow,和小(第二个参数的余数),使用 Math.pow,然后乘法。X将被复制到DOUBLE - 确保它不大于MAX_VALUE,A将是INT(最大2147483647但BigDecimal.pow无论如何都不支持超过十亿的整数),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

答案 2

指数 = 对数。

看看大十进制的对数


推荐