ここに別の選択肢があります。これはもともとC ++で書かれていたため、有限精度の整数(__int64など)をC ++にバックポートできます。利点は、(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!
乗算のオーバーフローをできるだけ回避するために、次のSTRICT順序で左から右に評価します。
n / 1 * (n-1) / 2 * (n-2) / 3 * ... * (n-r+1) / r
この順序で演算された整数演算が正確であることを示すことができます(つまり、丸め誤差はありません)。
scipy.misc.comb
scipy.special.comb
バージョンを支持して廃止されました0.10.0
。