sympy.binomial与scipy.special.comb输出差异问题:为何调用comb的代码返回错误结果?
sympy.binomial与scipy.special.comb输出差异问题:为何调用comb的代码返回错误结果?
嘿,这个问题我碰到过类似的,核心原因其实是浮点数精度丢失在搞鬼!
咱们先拆解一下问题:
- 你用
scipy.special.comb得到的结果离谱到上千万,而sympy.binomial能给出正确的~49.94,本质是两者的计算方式完全不同:scipy.special.comb默认返回浮点数(哪怕你没显式指定exact=False,这是它的默认行为)。当计算comb(n-j, m)/comb(n, m)时,对于n=100这种较大的数值,当j比较小时,comb(n-j, m)和comb(n,m)的数值非常接近,它们的比值在浮点数里会被舍入,导致1 - (comb(n-j, m)/comb(n,m))变成一个极小的数——甚至可能因为精度问题被近似为0,这样coeff / denominator就会变得极大,累加后自然得到那个离谱的大数。- 而
sympy.binomial是精确的符号运算,它会全程保持分数形式计算,完全不会有浮点数的精度损失,所以能得到正确的结果。
那怎么解决这个问题呢?给你两个方案:
方案一:让scipy的comb做精确计算
修改comb的调用参数,加上exact=True,让它返回精确的整数,再用分数运算避免精度丢失:
from scipy.special import comb from fractions import Fraction def coup(n=100, m=10): expectation = 0.0 for j in range(1, n + 1): coeff = ((-1)**(j-1)) * comb(n, j, exact=True) # 用Fraction保持精确分数运算 numerator = comb(n - j, m, exact=True) denominator_frac = 1 - Fraction(numerator, comb(n, m, exact=True)) expectation += coeff / denominator_frac print(expectation)
这样计算出来的结果就会和sympy版本完全一致,因为全程都是精确计算,没有浮点数误差。
方案二:继续使用sympy的binomial
如果你的场景对计算精度要求高,sympy的符号运算天生就适合这种场景,不需要额外调整,直接用它的binomial就好:
from sympy import binomial def coup(n=100, m=10): expectation = 0 for j in range(1, n + 1): coeff = ((-1)**(j-1)) * binomial(n, j) denominator = 1 - (binomial(n - j, m) / binomial(n, m)) expectation += coeff / denominator print(expectation)
它会自动处理精确的分数运算,不会出现精度丢失的问题。
备注:内容来源于stack exchange,提问作者bettersayhello
相关产品推荐
相关产品推荐

