【问题标题】:OverflowError: (34, 'Result too large') in Python溢出错误:(34,“结果太大”)在 Python 中
【发布时间】:2015-04-13 07:28:04
【问题描述】:

我正在编写一个小脚本,用于根据给定数据计算并绘制稀疏曲线。 (如维基百科中所述:http://en.wikipedia.org/wiki/Rarefaction_%28ecology%29) 但我尝试为 大于 170 的值绘制函数我不断收到以下错误:OverflowError: (34, 'Result too large')

这是一个包含一些数据的代码示例:

import numpy as np
import math
import matplotlib.pyplot as plt
import decimal

def pltCurve():
    data = [[367, 172, 503, 1404, 8, 83, 7, 2, 7, 1, 0, 6, 31, 0, 6, 40, 0, 18, 132, 41, 1, 2, 15, 1, 0, 10, 0, 63, 59, 3, 0, 7, 9, 9, 4, 0, 2, 0, 23, 20, 4, 0, 0, 1, 11, 55, 0, 0, 1, 1, 0, 1, 4, 11, 0, 10, 6, 0, 4, 0, 443, 2, 49, 29, 0, 5, 6, 0, 0, 1, 0, 0, 0, 0, 0, 32, 0, 1, 14, 1, 0, 1, 3, 1, 1, 0, 7, 0, 2, 32, 2, 1, 55, 0, 21, 1, 7, 2, 0, 0, 0, 0, 0, 0, 0, 1, 76, 5, 9, 28, 1, 0, 72, 0, 0, 0, 0, 61, 6, 5, 0, 5, 2, 0, 1, 9, 1, 0, 1, 1, 1, 1, 1, 1, 34, 28, 1, 1, 1, 3, 3, 0, 0, 1, 0, 0, 3, 1, 3, 55, 19, 18, 87, 0, 1, 2, 6, 15, 10, 1, 2]]

    for d in range(len(data)):
        x = np.arange(1,170 , 10)
        y = computeFn(d,x)
        #plt.plot(x,y)
        plt.errorbar(x,y,yerr=0.95)

    plt.show()

def computeFn(i, n):
    N = 4467
    res = []
    r = Decimal(0)
    numOfGroups = 161
    data = [[367, 172, 503, 1404, 8, 83, 7, 2, 7, 1, 0, 6, 31, 0, 6, 40, 0, 18, 132, 41, 1, 2, 15, 1, 0, 10, 0, 63, 59, 3, 0, 7, 9, 9, 4, 0, 2, 0, 23, 20, 4, 0, 0, 1, 11, 55, 0, 0, 1, 1, 0, 1, 4, 11, 0, 10, 6, 0, 4, 0, 443, 2, 49, 29, 0, 5, 6, 0, 0, 1, 0, 0, 0, 0, 0, 32, 0, 1, 14, 1, 0, 1, 3, 1, 1, 0, 7, 0, 2, 32, 2, 1, 55, 0, 21, 1, 7, 2, 0, 0, 0, 0, 0, 0, 0, 1, 76, 5, 9, 28, 1, 0, 72, 0, 0, 0, 0, 61, 6, 5, 0, 5, 2, 0, 1, 9, 1, 0, 1, 1, 1, 1, 1, 1, 34, 28, 1, 1, 1, 3, 3, 0, 0, 1, 0, 0, 3, 1, 3, 55, 19, 18, 87, 0, 1, 2, 6, 15, 10, 1, 2]]
    #print N
    for k in n:
        r = (sum((logchoose(N-N_i,k)) for N_i in data[i]))*(logchoose(N,k))**-1
        r = Decimal(numOfGroups) - r
        print r # Debug
        res.append(r)
    return res

def logchoose(ni, ki):

    """
    :rtype : N choose K Function
    """
    try:
        lgn1 = sum(math.log10(ii) for ii in range(1,ni))
        lgk1 = sum(math.log10(ii) for ii in range(1,ki))
        lgnk1 = sum(math.log10(ii) for ii in range(1,ni-ki+1))
    except ValueError:
        #print ni,ki
        raise ValueError
    #print 10**(lgn1 - (lgnk1 + lgk1))
    return Decimal((10**(lgn1 - (lgnk1 + lgk1))))


pltCurve()

我已经看到使用“十进制”模块解决此问题的方法。我玩过它,但仍然引发了错误。 有什么建议么? 问候。

编辑:这是确切的回溯:

    Traceback (most recent call last):
  File "C:\Users\user\Documents\Rarefactor\test.py", line 48, in <module>
    pltCurve()
  File "C:\Users\user\Documents\Rarefactor\test.py", line 11, in pltCurve
    y = computeFn(d,x)
  File "C:\Users\user\Documents\Rarefactor\test.py", line 26, in computeFn
    r = (sum((logchoose(N-N_i,k)) for N_i in data[i]))*(logchoose(N,k))**-1
  File "C:\Users\user\Documents\Rarefactor\test.py", line 26, in <genexpr>
    r = (sum((logchoose(N-N_i,k)) for N_i in data[i]))*(logchoose(N,k))**-1
  File "C:\Users\user\Documents\Rarefactor\test.py", line 45, in logchoose
    return (10**(lgn1 - (lgnk1 + lgk1)))
OverflowError: (34, 'Result too large')

【问题讨论】:

  • 不要只告诉我们错误描述,而是向我们展示完整的回溯,这样我们就可以知道这些可能引发错误的行中的哪一行实际上是这样做的,而不必猜测。跨度>
  • 或者,更好的是,给我们一个minimal, complete, verifiable example,它可以在不包含所有不相关内容的情况下重现问题。 (例如,如果在您使用绘图功能之前发生异常,则绘图内容显然不相关。但如果您不明白应该包含什么,请参阅链接的帮助页面以获得更详细的说明。)跨度>
  • @abarnert 感谢您的回复。似乎在 r = (sum((logchoose(N-N_i,k)) for N_i in data[i]))*(logchoose(N,k))**-1 处引发错误。计算函数的位置。但在尝试使用 Decimal 模块后,我仍然收到错误。
  • 请使用回溯发布异常。一次回答一个关于异常的问题,而不是仅仅向我们展示以便我们自己查看,这只会让任何想要帮助您的人变得更慢和更痛苦。
  • @dbliss:我不是 100% 确定这是一个 dup,因为他正在尝试使用一个大小合适的 NumPy 浮点数组,而不是一个浮点数,所以那里的最佳答案(“使用十进制而不是 float") 在这里可能不一定合适……

标签: python matplotlib


【解决方案1】:

您的异常来自这一行:

return (10**(lgn1 - (lgnk1 + lgk1)))

您尝试像这样使用Decimal 来修复它:

return Decimal(10**(lgn1 - (lgnk1 + lgk1)))

但这无济于事。因为lgn1lgnk1lgk1float 值,所以您尝试使用float 值进行算术运算,然后在完成后将结果转换为Decimal。因为float 算术溢出,所以它永远不会进行转换。

您需要做的是首先在Decimal 值上进行算术运算。例如:

lgn1 = Decimal(sum(math.log10(ii) for ii in range(1,ni)))
lgk1 = Decimal(sum(math.log10(ii) for ii in range(1,ki)))
lgnk1 = Decimal(sum(math.log10(ii) for ii in range(1,ni-ki+1)))

现在,当你这样做时:

return (10**(lgn1 - (lgnk1 + lgk1)))

...你有Decimal 算术,而不是float,它不会溢出(当然,只要你的Decimal 上下文足够大,可以容纳这些数字)。

但您可能希望将Decimal 推到链上尽可能高的位置,而不是尽可能低的位置。在这种情况下,这只是上一级——对整数调用 math.log10 会得到 float,但对 Decimal 调用 log10 方法会得到 Decimal,所以:

lgn1 = sum(Decimal(ii).log10() for ii in range(1, ni))

同时,供将来参考:

除了擦除绘图线之外,我看不出如何进一步最小化此代码。

那么,首先,为什么不把绘图线抹掉呢?

但是,更重要的是,您知道异常发生在 logchoose 函数的最后一行,并且您知道(或者可以知道,例如,通过添加 print ni, ki 或在调试器中运行)哪些参数使其升高。因此,您可以将整个事情简化为 logchoose 定义加上 print logchoose(273, 114)(或任何参数)。

除了更短之外,这也将完全排除 numpymatplotlib 的等式,因此对这些库一无所知但对 Python 了解很多的人(这是绝大多数,包括人比我、dbliss 和 Nimrodshn 聪明,或者至少比我聪明的人)可以解决你的问题。

【讨论】:

  • 这对我有帮助,就像 7 年后一样。病得很厉害。小问题:decimal.getcontext().prec = n,我的电脑上限制了 n。 RAM,CPU,GPU,...?我想说 RAM,但我不确定和好奇。
猜你喜欢
  • 2013-12-10
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-02-15
  • 1970-01-01
  • 2017-01-21
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多