我使用以下两个函数来计算阶乘和组合。
public static long Factorial(long n)
{
if (n == 0)
return 1;
else
return n * Factorial(n-1);
}
public static long combinations (long n, long k)
{
return Factorial(n)/(Factorial(k) * Factorial(n - k));
}
我正在测试它:
long test = combinations((long)21, (long)13);
它似乎适用于5,2
这样的小数字。但如果我尝试21,13
,我会得到错误的答案(否定或0)。
有人知道这里发生了什么吗?
答案 0 :(得分:1)
java中long
的最大值为2 ^ 63。
这将安全地将你带到20的阶乘。但是,21的阶乘达到2 ^ 65左右,所以你超过了可以表示的最大值。
如果执行导致溢出的乘法,请参阅this question以了解有关java中发生的情况的讨论。
答案 1 :(得分:1)
这主要是因为来自long
(64位已签名)的溢出。您可以在这种情况下查找BigDecimal或BigInteger。
答案 2 :(得分:0)
正如其他用户所说,长期不能持有Factorial(21)。我使用BigInteger重写了你的Factorial方法,它似乎有效,尽管你必须将BigInteger作为参数传递。
public static BigInteger Factorial(BigInteger n)
{
if (n.equals(BigInteger.ZERO))
return BigInteger.ONE;
else
return n.multiply(Factorial(n.subtract(BigInteger.ONE)));
}
然后使用BigInteger重写你的组合方法:
public static BigInteger combinations (BigInteger n, BigInteger k)
{
return Factorial(n).divide(Factorial(k).multiply(Factorial(n.subtract(k))));
}
在main方法中,我调用了像这样的组合方法
System.out.print(combinations(new BigInteger("21"), new BigInteger("13")));