1

我正在解决一个编程问题,该问题被困在nCr有效计算并同时避免溢出。我做了以下简单的简化,但我只是好奇是否有任何更复杂的简化可用。

(n)!/(n-k)!*k! = n*(n-1)*.....*(max(n-k+1, k))/(min(n-k, k-1))

考虑到 k 的不同情况是偶数还是奇数,是否还有更多的简化可能,只是提出一种方法。

任何评论表示赞赏。

4

2 回答 2

7

我在这里找到了一个有趣的解决方案:http: //blog.plover.com/math/choose.html

    unsigned choose(unsigned n, unsigned k) {
      unsigned r = 1;
      unsigned d;
      if (k > n) return 0;
      for (d=1; d <= k; d++) {
        r *= n--;
        r /= d;
      }
      return r;
    }

这通过交替执行乘法和除法来避免溢出(或至少限制问题)。

例如对于n = 8, k = 4:

result = 1;
result *= 8;
result /= 1;
result *= 7;
result /= 2;
result *= 6;
result /= 3;
result *= 5;
result /= 4;
done
于 2012-08-26T12:52:50.883 回答
0

我也必须解决这个问题。我所做的是利用乘法与除法相同数量的事实,并将它们捆绑在一起,一次进行一次乘法和一次除法。它最后以整数形式出现,但我使用 double 作为中间项,然后在最后四舍五入到最接近的整数。

// Return the number of combinations of 'n choose k'
unsigned int binomial(unsigned int n, unsigned int k) {
unsigned int higher_idx;
unsigned int lower_idx;
if(k > n-k) {
    higher_idx = k;
    lower_idx = n - k;
} else {
    higher_idx = n - k;
    lower_idx = k;
}
double product = 1.0;
double factor;
unsigned int idx;
for(idx=n; idx>higher_idx; idx--) {
    factor = (double)idx / double(lower_idx - (n - idx));
    product *= factor;
}
return (unsigned int)(product + 0.5);
}
于 2014-12-21T18:51:01.150 回答