优化计算组合,避免溢出

Ama*_*tam 1 c overflow

我正在解决一个编程问题,它nCr有效地计算,同时避免溢出.我做了以下简单的简化,但我很好奇是否有更复杂的简化可用.

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

考虑到k为偶数或奇数的不同情况,可以有更多的简化,只是建议一种方法.

任何评论表示赞赏.

Bar*_*ski 5

我在这里找到了一个有趣的解决方案: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;
    }
Run Code Online (Sandbox Code Playgroud)

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

例如n = 8,k = 4:

result = 1;
result *= 8;
result /= 1;
result *= 7;
result /= 2;
result *= 6;
result /= 3;
result *= 5;
result /= 4;
done
Run Code Online (Sandbox Code Playgroud)

  • @AmanDeepGautam:在循环的每次迭代中的除法语句之后,r的值为nCd,原始值为n,当前值为d.因此,当n从10开始时,第一次迭代将r设置为10(*10/1).第二次迭代将r设置为45(*9/2).第三次迭代将r设置为120(*8/3).这些是值10C1,10C2和10C3.我们知道nCd总是一个整数.因此,数学除法必须总是产生一个整数,因此,在除法之前,r必须是d的倍数. (3认同)