Optimizing calculating combination and avoiding overflows

夙愿已清 提交于 2020-06-09 04:00:06

问题


I am solving a programming problem which is stuck at calculating nCr efficiently and at the same time avoiding overflows. I have made the following trivial simplification but am just curious about if there are any more sophisticated simplifications available out there.

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

Can there be any more simplification possible considering different cases for k as even or odd, just suggesting a way.

Any comment is appreciated.


回答1:


I found an interesting solution here: 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;
    }

This avoids overflows (or at least limits the problem) by performing multiplication and division alternatively.

E.g. for n = 8, k = 4:

result = 1;
result *= 8;
result /= 1;
result *= 7;
result /= 2;
result *= 6;
result /= 3;
result *= 5;
result /= 4;
done



回答2:


I had to solve this problem, too. What I did was use the fact that there are the same number of multiplications as divisions and bundled them together, taking one multiplication and one division at a time. It comes out as an integer at the end, but I use double for the intermediate terms and then round to the nearest integer at the end.

// 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);
}


来源:https://stackoverflow.com/questions/12130094/optimizing-calculating-combination-and-avoiding-overflows

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!