简体   繁体   中英

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.

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. 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 . 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:*

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

So, the problem is that one of the terms in your equation is greater than the largest possible IEEE double.

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. 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 . So, use sys.float_info to see the max value for your platform. But it's almost always going to be 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. 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.

As abarnert pointed out, floats are limited in 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:

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.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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