0

1st of all, I'm trying to understand why I'm getting an overflow error. the first function "fibGen" works fine unless I give it an insanely large nth Fibonacci term.

    #the golden ration function
    def fibGen(num):
            for number in range(0,num+1):
                val = (golden_ratio**number - (1 - golden_ratio)**number) / math.sqrt(5)
                print('{i:3}: {v:3}'.format(i=number, v=round(val)))

The second function "elemFib" will give me the correct answer but then errors out if number is over 1500.

    #the find element < Max number function
    def elemFib(num):
            for number in range(0,num+1):
                val = (golden_ratio**number - (1 - golden_ratio)**number) / math.sqrt(5)
                if val < num:
                    print('Fib({}): {}'.format(number, round(val)))

lastly, the function "pythonic" works like the "elemFib" function and does not give me an error code for even a very large number, why is that? Also, I'm trying to get it to print the Fibonacci numbers like the first function "fibGen" but can't get it to work like that.

    #Pythonic way
    def pythonic(num):
        a, b = 0,1

        while a < num:
            print(a, sep=" ", end=" ")
            a, b = b, a+b

My complete code for your review:

    import math
    import time

    #create the golden Ratio formula
    golden_ratio = (1 + math.sqrt(5)) / 2

    #the timer function
    def clockTime(start_time):
        print('\nRun Time:', time.time() - start_time)

    #the golden ration function
    def fibGen(num):
            for number in range(0,num+1):
                val = (golden_ratio**number - (1 - golden_ratio)**number) / math.sqrt(5)
                print('{i:3}: {v:3}'.format(i=number, v=round(val)))

    #the find element < Max number function
    def elemFib(num):
            for number in range(0,num+1):
                val = (golden_ratio**number - (1 - golden_ratio)**number) / math.sqrt(5)
                if val < num:
                    print('Fib({}): {}'.format(number, round(val)))

    #Pythonic way
    def pythonic(num):
        a, b = 0,1

        while a < num:
            print(a, sep=" ", end=" ")
            a, b = b, a+b

    #display the Main Menu
    def dispMenu():
        print('---------------------Fibonacci Series ------------------\n')
        print('(A) Print Fibonacci numbers to the nth term')
        print('(B) Print Fibonacci numbers until element is less than Max number')
        print('(C) pythonic print')
        print('(Q) Quit the program\n')


    def  main():
              # set boolean control variable for loop
              loop = True

              #Create while loop for menu
              while loop:

                  #Display the menu
                  dispMenu()

                  #Get user's input
                  #choice = (input('Please make a selection: '))

                  #Get user's input
                  choice = input('Please make a selection: ').upper()

                  #Perform the selected action
                  if choice == 'A':
                      num = int(input("How many Fibonacci numbers should I print? "))
                      start_time = time.time()
                      fibGen(num)
                      clockTime(start_time)
                  elif choice == 'B':
                      num = int(input("the element should be less than? "))
                      start_time = time.time()
                      elemFib(num)
                      clockTime(start_time)
                  elif choice == 'C':
                      num = int(input('Pythonic Fibonacci series to the nth term? '))
                      start_time = time.time()
                      pythonic(num)
                      clockTime(start_time)
                  elif choice == 'Q':
                      print('\nExiting program, Thank you and Goodbye')
                      loop = False
                  else:
                      print('\nInvalid selection, try again\n')


    main()
Karl Knechtel
  • 62,466
  • 11
  • 102
  • 153
CelestialSky
  • 57
  • 2
  • 14
  • @Carcigenicate I don't see how my functions are recursive. My use of golden ration stems from Stack Overflow post https://stackoverflow.com/questions/494594/how-to-write-the-fibonacci-sequence?rq=1 – CelestialSky May 23 '19 at 16:44
  • Does this answer your question? [Why do I get "OverflowError: (34, 'Result too large')" or "OverflowError: (34, 'Numerical result out of range')" from floating-point exponentiation?](https://stackoverflow.com/questions/20201706/why-do-i-get-overflowerror-34-result-too-large-or-overflowerror-34) – Karl Knechtel Feb 13 '23 at 14:06

2 Answers2

1

Your functions crash once any value becomes too large. This is because internally, Python backs numbers with doubles.

Here is your elemFib function rewritten to use Decimals:

from decimal import Decimal

def elemFib(num):
        for number in range(0,num+1):
            val = golden_ratio ** Decimal(number) - (Decimal(1) - golden_ratio) ** Decimal(number) / Decimal(math.sqrt(5))
            if val < num:
                print('Fib({}): {}'.format(number, round(val)))

This won't crash like the original. All I did was replace all numbers with Decimal objects. They're slower but can grow arbitrarily.

The reason your pythonic function doesn't crash the same way is simply because it doesn't create crazy big numbers, while the other two work by raising the golden ratio to some exponent, which requires much larger numbers.

1

To expand on the explanation above, python integers will automatically be promoted to long data types so that it can hold any number. This feature has existed since python 2.2. Floats are limited, and they are not automatically promoted to Decimal types. Since the golden_ratio variable is a float, any calculation with it is limited unless you manually change the type.

https://www.python.org/dev/peps/pep-0237/

You can find out the max float value with sys.float_info:

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

Here you can see that the float cause an OverflowError but the Decimal or integer will not:

>>> 10.0 ** 309
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
OverflowError: (34, 'Numerical result out of range')
>>> Decimal(10.0) ** 309
Decimal('1.000000000000000000000000000E+309')
>>> 10 ** 309
1000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000L

Interestingly, the exponent operator ** raises an OverflowError exception, but multiplication just returns an inf float value:

>>> 2 * (10.0 ** 308)
inf
>>> -2 * (10.0 ** 308)
-inf
>>> math.isinf(2 * (10.0 ** 308))
True
egrubbs
  • 331
  • 1
  • 5