我正在为组合学问题编写一个强力解决方案,该问题涉及非常大的数字。我转向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一起使用吗?
这可能是什么问题?在此先感谢您的帮助。
答案 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
,以便将它们转换为BigInteger
。 BigInteger
没有带整数值的构造函数,但它有一个static valueOf
method。