【问题标题】:OverflowError: (34, 'Result too large')溢出错误:(34,'结果太大')
【发布时间】:2013-12-10 16:31:48
【问题描述】:

我收到溢出错误(OverflowError: (34, 'Result too large')
我想将 pi 计算到小数点后 100,这是我的代码:

def pi(): 
    pi = 0 
    for k in range(350): 
        pi += (4./(8.*k+1.) - 2./(8.*k+4.) - 1./(8.*k+5.) - 1./(8.*k+6.)) / 16.**k 
    return pi 
print(pi())

【问题讨论】:

  • for k in range(350): 太大,导致此问题。

标签: python overflow decimal pi


【解决方案1】:

您达到了平台对float 支持的限制,可能在k = 256 之后:

>>> k = 256
>>> (4./(8.*k+1.) - 2./(8.*k+4.) - 1./(8.*k+5.) - 1./(8.*k+6.)) / 16.**k
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
OverflowError: (34, 'Result too large')
>>> k = 255
>>> (4./(8.*k+1.) - 2./(8.*k+4.) - 1./(8.*k+5.) - 1./(8.*k+6.)) / 16.**k
3.19870064997e-313

请参阅sys.float_info 了解确切的限制,但您不太可能遇到当前 CPU 和操作系统组合在任何情况下都会为您提供 100 个有效数字的情况;我的 64 位 OS X 的 MacBook Pro 只支持 15。

使用decimal module 超越您的硬件限制。

from decimal import Decimal, localcontext

def pi(): 
    with localcontext() as ctx:
        ctx.prec = 100  # 100 digits precision
        pi = Decimal(0) 
        for k in range(350): 
            pi += (Decimal(4)/(Decimal(8)*k+1) - Decimal(2)/(Decimal(8)*k+4) - Decimal(1)/(Decimal(8)*k+5) - Decimal(1)/(Decimal(8)*k+6)) / Decimal(16)**k 
    return pi 

【讨论】:

    【解决方案2】:

    Python 浮点数既不是任意精度,也不是无限大小。当 k = 349 时,16.**k 太大了——几乎是 2^1400。幸运的是,decimal 库允许任意精度并且可以处理大小:

    import decimal
    decimal.getcontext().prec = 100
    def pi():
        pi = decimal.Decimal(0)
        for k in range(350):
            pi += (decimal.Decimal(4)/(decimal.Decimal(8)*decimal.Decimal(k+1))...)
    

    【讨论】:

      【解决方案3】:

      16.**256 太大而无法存储在双精度浮点数中。我建议您使用更少的周期,例如 range(250),因为较大的 k 值无论如何都不会影响前一百位数。

      您可以尝试的另一件事是乘以 16.*(-k) 而不是除以 16.*k。对于较大的 k,此数字将四舍五入为零,因此不会给您带来运行时错误。

      我建议您使用 numpy.power 而不是 **,它可以更好地处理溢出。例如,在您的代码中,numpy.power(16.,256) 将计算为 inf,并将有限数除以 inf 得到零,这可以避免运行时错误,就像上一段中建议的方法一样。

      【讨论】:

        【解决方案4】:

        我用python3.6 AMD64,我也遇到这个问题,这是因为python内置float是双精度浮点型,是64位的,在大多数编程任务中,64位就足够了,但在某些情况下额外的任务,还不够(如科学计算,大数据计算)

        【讨论】:

          【解决方案5】:

          这是使用十进制库解决此问题的python 解决方案。此代码计算了一千位 pi。

          import decimal
          def pi( prec = 10 ** 3 ):
              decimal.getcontext().prec = prec
              b =  decimal.Decimal(1)
              pi = 0
              for k in range(prec):
                  pi += ( b*4/(8*k+1) - b*2/(8*k+4) - b*1/(8*k+5) - b*1/(8*k+6)) / 16**k
              return pi
          print(pi())
          

          这是一个仅使用内置任意大小整数的解决方案。它的工作效率更高,并且可以让您计算一万位数的 pi。

          def pi( prec = 10 ** 4 ):
              b = 10 ** prec
              pi = 0
              for k in range(prec):
                  pi += ( b*4//(8*k+1) - b*2//(8*k+4) - b*1//(8*k+5) - b*1//(8*k+6)) // 16**k
              return pi
          print(pi())
          

          通过启动此代码,您可以向您的朋友吹嘘您已经数了一万个 pi :)。

          【讨论】:

            【解决方案6】:

            如果您需要几乎无限的精度,请使用小数。

            在极少数情况下,如果您正在做n ** 2 或类似的事情。您可以通过将其转换为n * n 来避免错误而不会捕获它,因此取决于您如何解决此问题,它可能是解决此问题的可靠方法。您的号码将被称为 inf 而不是引发错误,** 执行幂函数并且是引发错误的那个。

            【讨论】:

              猜你喜欢
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 2017-02-15
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 2017-01-21
              相关资源
              最近更新 更多