在项目Euler解决问题(剧透)中,这对我来说是一个问题:
Python2.7.10/0.13.0b1: scipy.misc.comb(40,20) -> array(137846528819.9994)
Python3.5.0/scipy 0.16.0: scipy.misc.comb(40,20) -> 137846528820.00006
令人沮丧的是,我了解到我必须round()在结果上调用函数,而不是直接转换为int()使用math.floor()/ math.ceil()用于Python 2/3的一致性.
导致两个Python/SciPy版本之间出现这种差异的原因是什么?
有没有理由SciPy开发人员不只是首先调用round()返回的结果scipy.misc.comb()?
如果使用exact=True参数,则可以获得相同的整数(长整数)值.
Run Code Online (Sandbox Code Playgroud)exact : bool, optional If `exact` is False, then floating point precision is used, otherwise exact long integer is computed.
我没有安装足够的版本,但我怀疑浮点差异与版本13和14之间的代码更改有关.13返回array()结果,14(及更高版本)返回浮点数(numpy.float64) .
我建议查看Python代码本身,看看有什么不同.在exact他们看起来相同的情况下,但浮动的情况是完全不同的.
第13节:
from scipy import special
k,N = asarray(k), asarray(N)
lgam = special.gammaln
cond = (k <= N) & (N >= 0) & (k >= 0)
sv = special.errprint(0)
vals = exp(lgam(N+1) - lgam(N-k+1) - lgam(k+1))
sv = special.errprint(sv)
return where(cond, vals, 0.0)
Run Code Online (Sandbox Code Playgroud)
第14节
k,N = asarray(k), asarray(N)
cond = (k <= N) & (N >= 0) & (k >= 0)
vals = binom(N, k)
if isinstance(vals, np.ndarray):
vals[~cond] = 0
elif not cond:
vals = np.float64(0)
return vals
Run Code Online (Sandbox Code Playgroud)
该exact代码是迭代的,并且可以是较慢的(当N,k为在100秒):
val = 1
for j in xrange(min(k, N-k)):
val = (val*(N-j))//(j+1)
Run Code Online (Sandbox Code Playgroud)