查看您的代码,难怪您会很快耗尽内存。您的方法divideFactorials
调用方法阶乘并使用差异“分子-分母”作为参数。根据您的代码,这种差异很可能会非常大,并且您将在阶乘方法中陷入很长的循环中。
如果它真的只是为了找到 nCk(我假设这是因为您在代码中的注释),只需使用:
public static long GetnCk(long n, long k)
{
long bufferNum = 1;
long bufferDenom = 1;
for(long i = n; i > Math.Abs(n-k); i--)
{
bufferNum *= i;
}
for(long i = k; i => 1; i--)
{
bufferDenom *= i;
}
return (long)(bufferNom/bufferDenom);
}
当然使用这种方法你会很快超出范围,因为 long 实际上并不支持很长的数字,所以 n 和 k 必须小于 20。
假设您实际上使用非常大的数字,您可以使用双精度数而不是长数,因为幂变得越来越重要。
编辑:
如果您使用大量数字,您也可以使用斯特林公式:
随着 n 变大 ln(n!) -> n*ln(n) - n。
将其放入代码中:
public static double GetnCk(long n, long k)
{
double buffern = n*Math.Log(n) - n;
double bufferk = k*Math.Log(k) - k;
double bufferkn = Math.Abs(n-k)*Math.Log(Math.Abs(n-k)) - Math.Abs(n-k);
return Math.Exp(buffern)/(Math.Exp(bufferk)*Math.Exp(bufferkn));
}
我只提出这个答案,正如你所说的与语言无关,C#代码只是用来演示它。由于您需要对 n 和 k 使用较大的数字才能使其起作用,因此我建议将其作为查找大型组合的二项式系数的一般方法。
对于 n 和 k 都小于 200-300 左右的情况,您应该使用 Victor Mukherjee 提出的答案,因为它是准确的。
Edit2:
编辑了我的第一个代码。