首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >如何在python中计算昂贵的高精度和?

如何在python中计算昂贵的高精度和?
EN

Stack Overflow用户
提问于 2014-02-03 18:50:02
回答 2查看 584关注 0票数 8

我的问题很简单。我想计算一下下面的总和。

代码语言:javascript
复制
from __future__ import division
from scipy.misc import comb
import math

for n in xrange(2,1000,10):
    m = 2.2*n/math.log(n)
    print sum(sum(comb(n,a) * comb(n-a,b) * (comb(a+b,a)*2**(-a-b))**m
                    for b in xrange(n+1))
               for a in xrange(1,n+1))

但是,python提供了RuntimeWarning: overflow encountered in multiplynan作为输出,而且速度也非常慢。

有什么聪明的办法吗?

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2014-02-03 19:39:03

你之所以得到NaNs,是因为你最终评估的数字如下

代码语言:javascript
复制
comb(600 + 600, 600) == 3.96509646226102e+359

它太大,不适合于浮点数:

代码语言:javascript
复制
>>> numpy.finfo(float).max
1.7976931348623157e+308

取对数以避免:

代码语言:javascript
复制
from __future__ import division, absolute_import, print_function
from scipy.special import betaln
from scipy.misc import logsumexp
import numpy as np


def binomln(n, k):
    # Assumes binom(n, k) >= 0
    return -betaln(1 + n - k, 1 + k) - np.log(n + 1)


for n in range(2, 1000, 10):
    m = 2.2*n/np.log(n)

    a = np.arange(1, n + 1)[np.newaxis,:]
    b = np.arange(n + 1)[:,np.newaxis]

    v = (binomln(n, a) 
         + binomln(n - a, b) 
         + m*binomln(a + b, a) 
         - m*(a+b) * np.log(2))

    term = np.exp(logsumexp(v))
    print(term)
票数 16
EN

Stack Overflow用户

发布于 2014-02-03 19:26:06

使用追忆模式。在此之后,重新定义梳子:

代码语言:javascript
复制
@memoized
def newcomb(a, b):
    return comb(a, b)

并将对comb的所有调用替换为newcomb。另外,为了略有改进,去掉括号。如果列出了明确的列表,就会浪费时间来构建它们。如果您删除它们,您将有效地使用生成器表达式

更新

这不会解决nan问题,但确实会使它变得更快。

对于那些不认为这更快的人来说,你是在申请回忆录装饰师吗?在我的机器上,最初的功能需要29.7秒才能达到200,但回忆录版本只需要3.8秒。

回忆录所做的只是将您对comb的所有调用存储在一个查找表中。因此,如果在以后的迭代中使用与过去相同的参数调用comb,那么它不会重新计算它--它只是在查找表中查找它。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/21535277

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档