2 вопроса, Python OverflowError: (34, 'Результат слишком большой') и неверные результаты функции - PullRequest
0 голосов
/ 23 мая 2019

Во-первых, я пытаюсь понять, почему я получаю ошибку переполнения. первая функция "fibGen" работает нормально, если я не дам ей безумно большой n-й член Фибоначчи.

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

Вторая функция "elemFib" даст мне правильный ответ, но затем выдаст ошибку, если число превысит 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)))

наконец, функция «pythonic» работает как функция «elemFib» и не дает мне код ошибки даже для очень большого числа, почему это так? Кроме того, я пытаюсь получить он должен печатать числа Фибоначчи, как первая функция «fibGen», но не может заставить ее работать так.

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

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

Мой полный код для вашего обзора:

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

Ответы [ 2 ]

1 голос
/ 29 мая 2019

Чтобы расширить объяснение выше, целые числа Python будут автоматически преобразованы в длинные типы данных, чтобы они могли содержать любое число. Эта функция существует с Python 2.2. Число с плавающей точкой ограничено, и они не автоматически переводятся в десятичные типы. Поскольку переменная golden_ratio является плавающей точкой, любые вычисления с ней ограничены, если вы не измените тип вручную.

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

Максимальное значение с плавающей точкой можно узнать с помощью 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)

Здесь вы можете видеть, что число с плавающей запятой вызывает OverflowError, но десятичное число или целое число не будут:

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

Интересно, что оператор экспоненты ** вызывает исключение OverflowError, но умножение просто возвращает значение inf с плавающей запятой:

>>> 2 * (10.0 ** 308)
inf
>>> -2 * (10.0 ** 308)
-inf
>>> math.isinf(2 * (10.0 ** 308))
True
1 голос
/ 28 мая 2019

Ваши функции перестают работать, когда любое значение становится слишком большим.Это связано с тем, что внутренне Python поддерживает числа с удваивается .

Вот ваша функция elemFib, переписанная для использования Decimal s:

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 выиграла 'т сбой, как оригинал.Все, что я сделал, это заменил все числа на Decimal объектов.Они медленнее, но могут расти произвольно.

Причина, по которой ваша pythonic функция не падает таким же образом, заключается просто в том, что она не создает сумасшедших больших чисел, в то время как две другие работают, поднимая золотуюотношение к некоторому показателю степени, который требует гораздо больших чисел.

...