错误34,结果太大

时间:2014-10-21 22:11:19

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

我正在尝试打印Fibonacci序列,并且在大约第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')

2 个答案:

答案 0 :(得分:3)

嗯,首先,让我们把那个大表达分成小的表达式,这样我们就可以看出它出了什么问题。并使用调试器或一些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') 引发此异常。你可以很容易地验证:

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

那么,为什么这是一个问题?

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

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

所以,问题是你方程中的一个项大于最大可能的IEEE双。

这意味着你需要选择不同的算法,**或者获得一个“大浮动”库。

碰巧,Python在decimal模块中有一个内置的big-float库。当然顾名思义,它处理十进制浮点数,而不是二进制浮点数,因此如果你使用它会得到不同的舍入错误。但是考虑到你的代码,你可能并不关心舍入错误。

所以:

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

......然后......

float

*事实上,限制是特定于平台的;实现不是必需使用IEEE {1}}的双精度数。因此,使用sys.float_info查看平台的最大值。但它几乎总是1.7976931348623157e+308

**请注意,您使用的算法与天真算法相比的唯一优势是它允许您直接逼近第N个斐波纳契数,而无需计算前面的N-1。但是既然你想要将它们打印出来,那么你就没有任何优势。你只是得到了缺点 - 这是一个近似值;它更复杂;它需要浮点数学,这可能会出现舍入误差;它比较慢;它需要更多的记忆;在大多数平台上,大多数语言中的内置浮点类型都不能容纳F(605),......所有这些都没有任何好处似乎不值得。

答案 1 :(得分:1)

正如abarnert指出的那样,浮游物在蟒蛇中是有限的。您可以通过

查看限制
>>> 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))

但是,由于斐波纳契序列呈指数增长,你很快就会碰到同一堵墙。尝试通过保留最后两个术语并添加它们来计算Fibonacci。这样你就可以使用整数。