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

时间:2015-07-23 05:03:17

标签: java biginteger bigdecimal integer-overflow

我正在为组合学问题编写一个强力解决方案,该问题涉及非常大的数字。我转向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一起使用吗? 这可能是什么问题?在此先感谢您的帮助。

1 个答案:

答案 0 :(得分:2)

3 20 太大而不适合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