以下是另一种选择。这个方法最初是用C++编写的,因此可以将其移植到C++上,以获得有限精度整数(例如__int64)。其优点是(1)它仅涉及整数运算,(2)通过执行连续的乘法和除法对整数值进行膨胀。
我已经使用Nas Banov的Pascal三角形测试了结果,它得到了正确的答案:
def choose(n,r):
"""Computes n! / (r! (n-r)!) exactly. Returns a python long int."""
assert n >= 0
assert 0 <= r <= n
c = 1L
denom = 1
for (num,denom) in zip(xrange(n,n-r,-1), xrange(1,r+1,1)):
c = (c * num) // denom
return c
原因:为了最小化乘除法的数量,我们将表达式重写为
n! n(n-1)...(n-r+1)
--------- = ----------------
r!(n-r)! r!
为了尽可能避免乘法溢出,我们将按照以下严格的顺序从左到右进行评估:
n / 1 * (n-1) / 2 * (n-2) / 3 * ... * (n-r+1) / r
我们可以证明按照这个顺序进行整数运算是精确的(即没有舍入误差)。
0.10.0
版本起,scipy.misc.comb
已被弃用,建议使用scipy.special.comb
。 - Dilawar