如何计算大中间值的和

时间:2013-04-16 18:50:13

标签: python math

我想计算

S = n  + m - \sum_{k=1}^{n} k^{k-1} \binom{n}{k} \frac{(n-k)^{n+m-k}}{n^{n+m-1}}

n m ,两个值的整数范围最大为1000.最终结果是一个数字不比 n 大很多但是对于python来说,中间值太大了。你怎么解决这个问题?

我将函数定义如下。

from scipy.misc import comb
def S(n,m):
    return n+m-sum([k**(k - 1)*comb(n, k)*(n - k)**(n + m - k)/n**(n + m - 1) for k in xrange(1,n+1)])

例如,我为n=m=100获得的错误是

RuntimeWarning: overflow encountered in multiply
  return n+m-sum([k**(k - 1)*comb(n, k)*(n - k)**(n + m - k)/n**(n + m - 1) for k in xrange(1,n+1)])
[...]
OverflowError: long int too large to convert to float

2 个答案:

答案 0 :(得分:4)

似乎问题出现在scipy的comb定义中。当我提供自制版本时,它可以正常工作:

import math

def choose(n,k):
    return math.factorial(n) / (math.factorial(k)*math.factorial(n-k))

comb = choose

def S(n,m):
    return n+m-sum([k**(k - 1)*comb(n, k)*(n - k)**(n + m - k)/n**(n + m - 1) for k in xrange(1,n+1)])

print S(1000,1000)

结果(约1.5秒):

1844

作为编写自己的comb的替代方法,请尝试将True的可选exact参数传递给comb。看起来你会得到一个漂浮,否则可能会搞砸了。

答案 1 :(得分:2)

在这种情况下,

scipy.misc.comb返回一个浮点数的ndarray。其余的计算是用整数完成的(最终在Python中的长整数< 3)。当浮点数乘以int时,Python会尝试将其转换为浮点数,但99 ** 199~1e397不适合Python浮点数(64位),因此会引发错误。

解决方案是将exact=True作为参数传递给comb。顺便说一下,你可以删除[里面的]sum:这可以避免内部列表的创建,因此它应该更快,内存效率更高(它类似于rangexrange)。如果您碰巧正在添加浮点数(此处不需要),那么使用math.fsum(精确的浮点值和)比sum要好得多。