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, большие вычислительные данные)