简体   繁体   English

错误34,结果太大

[英]Error 34, Result too large

I am trying to print the Fibonacci sequence and it always returns an Overflow error after about the 600th term. 我正在尝试打印斐波那契数列,并且总是在第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()

When I run this: 当我运行这个:

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')

Well, first, let's split that big expression up into smaller ones, so we can see where it's going wrong. 好吧,首先,让我们将大表达式分解为较小的表达式,这样我们就可以看出问题出在哪里。 And use a debugger or some print statements to see what values are making it go wrong. 并使用调试器或一些print语句查看导致错误的值。 That way, we're not just taking a stab in the dark. 这样,我们不只是在黑暗中刺伤。

If you do that, you can tell that (1+sqrt(5)**n_count) is raising this exception when n_count hits 605 . 如果这样做,则(1+sqrt(5)**n_count)n_count达到605(1+sqrt(5)**n_count)正在引发此异常。 Which you can verify pretty easily: 您可以很容易地验证:

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

So, why is that a problem? 那么,为什么会有问题呢?

Well, Python float values, unlike its integers, aren't arbitrary-sized, they can only hold what an IEEE double can hold:* 好吧,Python float值与整数不同,它不是任意大小的,它们只能容纳IEEE double可以容纳的值:*

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

So, the problem is that one of the terms in your equation is greater than the largest possible IEEE double. 因此,问题在于方程式中的一项大于最大可能的IEEE两倍。

That means you either need to pick a different algorithm,** or get a "big-float" library. 这意味着您要么需要选择其他算法,要么需要一个“大型”库。

As it happens, Python has a built-in big-float library, in the decimal module. 碰巧的是,Python在decimal模块中有一个内置的大浮点库。 Of course as the name implies, it handles decimal floats, not binary floats, so you'll get different rounding errors if you use it. 当然,顾名思义,它处理的是十进制浮点数,而不是二进制的浮点数,因此,如果使用它,则会遇到不同的舍入错误。 But you presumably don't care much about rounding errors, given your code. 但是,考虑到您的代码,您大概不太在乎舍入错误。

So: 所以:

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

… then … … 然后 …

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

* In fact, the limits are platform-specific; *实际上,限制是特定于平台的; implementations aren't required to use IEEE doubles for float . 不需要将IEEE double用作float So, use sys.float_info to see the max value for your platform. 因此,使用sys.float_info查看平台的最大值。 But it's almost always going to be 1.7976931348623157e+308 . 但这几乎总是1.7976931348623157e+308

** Note that the only advantage of the algorithm you're using over the naive one is that it allows you to approximate the Nth Fibonacci number directly, without calculating the preceding N-1. **请注意,与单纯算法相比,您所使用的算法的唯一优势在于,它无需计算前面的N-1,即可直接近似第N个斐波纳契数。 But since you want to print them all out anyway, you're not getting any advantage. 但是,由于您仍然希望将它们全部打印出来,因此没有任何优势。 You're just getting the disadvantages—it's an approximation; 您只是在获取缺点,这是一个近似值。 it's more complicated; 更复杂; it requires floating-point math, which is subject to rounding error; 它需要浮点数学运算,容易产生舍入误差; it's slower; 慢一点 it takes more memory; 它需要更多的内存; the built-in floating-point types in most languages on most platforms can't hold F(605), … All that for no benefit doesn't seem worth it. 大多数平台上大多数语言中的内置浮点类型无法容纳F(605),…所有这些毫无用处的做法似乎都不值得。

As abarnert pointed out, floats are limited in python. 正如abarnert指出的那样,浮点数在python中受到限制。 You can see the limit by 您可以通过以下方式查看限制

>>> 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)

You will reach some more terms if you divide by 2 before raising to the power: 如果在提高幂之前除以2,将会得到更多的项:

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

But since Fibonacci sequence grows exponentially, you will soon hit the same wall. 但是,由于斐波那契数列呈指数增长,因此您很快就会遇到同样的问题。 Try computing Fibonacci by holding the last two terms and adding them. 尝试通过持有最后两个项并将其相加来计算斐波那契。 That way you will use ints. 这样,您将使用整数。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM