除以阶乘时,BigDecimal 除法会崩溃

BigDecimal division breaks down when dividing by factorials

我正在为涉及除以非常大的数字的组合问题编写一个强力解决方案。我求助于 BigInteger 和 BigDecimal 来处理这些问题,但是当阶乘变得足够大以至于我无法确定时,我遇到了一个错误。

    int n = num;
    int k = num;
    BigDecimal sum = new BigDecimal("0");
    BigDecimal factorialN = new BigDecimal(factorial(n));
    BigInteger factorialI;
    BigInteger factorialJ;
    BigInteger factorialM;
    BigInteger denominator;
    double threePowerN = pow(3, n);        

    for (int i = 0; i < k; i++) {
        for (int j = 0; j < k; j++) {
            for (int m = 0; m < k; m++) {

                if (i + j + m == n) { 
                    factorialI = factorial(i);
                    factorialJ = factorial(j);
                    factorialM = factorial(m);
                    denominator = factorialI.multiply(factorialJ);
                    denominator = denominator.multiply(factorialM);
                    denominator = denominator.multiply(new BigInteger(String.valueOf((int)threePowerN)));
                    BigDecimal lastTerm = new BigDecimal(denominator);
                    lastTerm = factorialN.divide(lastTerm, 100, RoundingMode.HALF_EVEN);
                    sum = sum.add(lastTerm);
                }
            }
        }
    }
    // prints
    // -0.62366051209329651, which doesn't make sense because this should 
    // be a percentage between 0 and 1. 
    System.out.println(new BigDecimal("1").subtract(sum));

这里是 factorial 方法:

 public static BigInteger factorial(int n) {
    BigInteger result = BigInteger.ONE;
    while (n != 0) {
        result = result.multiply(new BigInteger(n + ""));
        n--;
    }
    return result;
} 

所有其他情况,从 n = k = num = 1 到 19,都按预期工作:打印值介于 0 和 1 之间。 一旦我达到 num = 20,sum 超过 1,并且 sum - 1 变为负数,这让我认为这里存在溢出问题。但这可以与 BigIntegers/BigDecimals 一起使用吗? 这里可能是什么问题?在此先感谢您的帮助。

320 太大,无法放入 int。所以这会失败:

  denominator = denominator.multiply(new BigInteger(String.valueOf((int)threePowerN)));

转换将环绕,您实际上将乘以一个负数。

BigInteger 有一个 pow 函数。而不是:

double threePowerN = pow(3, n);        

尝试

BigInteger threePowerN = BigInteger.valueOf(3).pow(n);

然后

denominator = denominator.multiply(threePowerN);

顺便说一下,您不必将整数转换为 String 即可将它们转换为 BigIntegerBigInteger 没有采用整数值的构造函数,但它确实有一个 static valueOf method.