OverflowError: (34, "Слишком большой результат" )

Я получаю ошибку переполнения (OverflowError: (34, "Слишком большой результат" )
Я хочу рассчитать pi до 100 десятичных знаков здесь мой код:

def pi(): 
    pi = 0 
    for k in range(350): 
        pi += (4./(8.*k+1.) - 2./(8.*k+4.) - 1./(8.*k+5.) - 1./(8.*k+6.)) / 16.**k 
    return pi 
print(pi())

Ответ 1

Поплавки Python не являются ни абсолютной точностью, ни неограниченным размером. Когда k = 349, 16.**k слишком велико - это почти 2 ^ 1400. К счастью, библиотека decimal допускает произвольную точность и может обрабатывать размер:

import decimal
decimal.getcontext().prec = 100
def pi():
    pi = decimal.Decimal(0)
    for k in range(350):
        pi += (decimal.Decimal(4)/(decimal.Decimal(8)*decimal.Decimal(k+1))...)

Ответ 2

Вы достигли пределов поддержки платформы float, возможно, после k = 256:

>>> k = 256
>>> (4./(8.*k+1.) - 2./(8.*k+4.) - 1./(8.*k+5.) - 1./(8.*k+6.)) / 16.**k
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
OverflowError: (34, 'Result too large')
>>> k = 255
>>> (4./(8.*k+1.) - 2./(8.*k+4.) - 1./(8.*k+5.) - 1./(8.*k+6.)) / 16.**k
3.19870064997e-313

См. sys.float_info для точных ограничений, но вряд ли вы столкнетесь с текущей комбинацией процессоров и ОС, которая в любом случае даст вам 100 значащих цифр; мой MacBook Pro с 64-разрядной ОС X будет поддерживать только 15.

Используйте decimal модуль, чтобы выйти за рамки ограничений вашего оборудования.

from decimal import Decimal, localcontext

def pi(): 
    with localcontext() as ctx:
        ctx.prec = 100  # 100 digits precision
        pi = Decimal(0) 
        for k in range(350): 
            pi += (Decimal(4)/(Decimal(8)*k+1) - Decimal(2)/(Decimal(8)*k+4) - Decimal(1)/(Decimal(8)*k+5) - Decimal(1)/(Decimal(8)*k+6)) / Decimal(16)**k 
    return pi 

Ответ 3

16. ** 256 слишком велико, чтобы быть сохраненным в float с двойной точностью. Я предлагаю вам запустить ваш цикл меньше, например, диапазон (250), потому что большие значения k не будут вносить вклад в первую сотню цифр.

Еще одна вещь, которую вы можете попробовать - умножить на 16. * (- k) вместо деления на 16. * k. Это число будет округлено до нуля для больших k, поэтому не даст вам ошибок времени выполнения.

Я предлагаю вам использовать numpy.power вместо **, он лучше обрабатывает переполнения. Например, в вашем коде numpy.power(16., 256) будет оцениваться значение inf и деление конечного числа на inf дает ноль, что позволяет избежать ошибок во время выполнения, как и метод, предложенный в предыдущем абзаце.

Ответ 4

Я использую python3.6 AMD64, я также встречаю эту проблему, потому что встроенный float python - это double-precision-float, это 64 бит, в большинстве задач для прогаммирования достаточно 64 бит, но в некоторых дополнительная задача, этого недостаточно (например, scitific computing, большие вычислительные данные)