【问题标题】:Error 34, Result too large错误 34,结果太大
【发布时间】:2014-10-21 22:11:18
【问题描述】:

我正在尝试打印斐波那契数列,但它总是在第 600 项之后返回溢出错误。

def fib():

    import math
    from math import sqrt
    print "\nFibonacci Sequence up to the term of what?"
    n=raw_input(prompt)
    if n.isdigit():
        if int(n)==0:
            return 0
        elif int(n)==1:
            return 1
        else:
            n_count=2
            print "\n0\n1"
            while n_count<int(n):
                fib=int(((1+sqrt(5))**n_count-(1-sqrt(5))**n_count)/(2**n_count*sqrt(5)))
                print fib
                n_count+=1
            fib()
    else:
        print "\nPlease enter a number."
        fib()
fib()

当我运行这个时:

Traceback (most recent call last):
  File "<pyshell#21>", line 1, in <module>
    fib()
  File "<pyshell#20>", line 15, in fib
    fib=int(((1+sqrt(5))**n_count-(1-sqrt(5))**n_count)/(2**n_count*sqrt(5)))
OverflowError: (34, 'Result too large')

【问题讨论】:

  • 请注意,这实际上不会打印斐波那契数列,它会打印斐波那契数列的粗略近似值——而且它会以一种比打印实际序列效率低的方式来打印。这真的是你想要的吗?
  • 另外,因为你用递归来伪造一个循环而不是仅仅使用一个循环,一旦你解决了这个问题,你就会在第 1000 次尝试打印时得到一个 RecursionError斐波那契数。

标签: python python-2.7 overflow python-2.x fibonacci


【解决方案1】:

嗯,首先,让我们将这个大表达式拆分成更小的表达式,这样我们就可以看到哪里出了问题。并使用调试器或一些print 语句来查看导致它出错的值。这样一来,我们就不仅仅是在黑暗中冒险了。

如果你这样做,你可以知道(1+sqrt(5)**n_count)n_count 命中605 时引发了这个异常。您可以很容易地验证:

>>> (1+sqrt(5))**604
1.1237044275099689e+308
>>> (1+sqrt(5))**605
OverflowError: (34, 'Result too large')

那么,为什么会有这样的问题?

嗯,Python float 的值,不像它的整数,不是任意大小的,它们只能容纳 IEEE double 可以容纳的值:*

>>> 1e308
1e308
>>> 1e309
inf

所以,问题在于方程中的一项大于最大可能的 IEEE 双倍。

这意味着您要么需要选择不同的算法**,要么获得“大浮点”库。

碰巧的是,Python 在decimal 模块中有一个内置的大浮点库。当然,顾名思义,它处理的是 decimal 浮点数,而不是 binary 浮点数,因此如果使用它,您会得到不同的舍入误差。但是考虑到您的代码,您可能不太关心舍入错误。

所以:

import decimal
s5 = decimal.Decimal(5).sqrt()

……然后……

fib=int(((1+s5)**n_count-(1-s5)**n_count)/(2**n_count*s5))

* 实际上,这些限制是特定于平台的;对于float 使用 IEEE 双精度实现不是必需。因此,请使用sys.float_info 查看您平台的最大值。但它几乎总是1.7976931348623157e+308

** 请注意,与简单算法相比,您使用的算法的唯一优势是它允许您直接逼近第 N 个斐波那契数,而无需计算前面的 N-1。但是,由于您无论如何都想将它们全部打印出来,因此您没有任何优势。你只是得到了缺点——这是一个近似值;它更复杂;它需要浮点数学,这会产生舍入误差;它更慢;它需要更多的内存;大多数平台上的大多数语言中的内置浮点类型都无法容纳 F(605),……所有这些无益的东西似乎不值得。

【讨论】:

    【解决方案2】:

    正如 abarnert 指出的,浮点数在 python 中是有限的。您可以通过

    查看限制
    >>> import sys
    >>> sys.float_info
    sys.float_info(max=1.7976931348623157e+308, max_exp=1024, max_10_exp=308, min=2.2250738585072014e-308, min_exp=-1021, min_10_exp=-307, dig=15, mant_dig=53, epsilon=2.220446049250313e-16, radix=2, rounds=1)
    

    如果你在加到幂之前除以 2,你会得到更多的条件:

    int(( ((1+sqrt(5))/2)**n_count - ((1-sqrt(5))/2)**n_count)/sqrt(5))
    

    但由于斐波那契数列呈指数增长,您很快就会遇到同样的问题。尝试通过保留最后两项并将它们相加来计算斐波那契。这样你就可以使用整数了。

    【讨论】:

      猜你喜欢
      • 2013-12-10
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-07-18
      • 1970-01-01
      • 2017-02-15
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多