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())
4 ответов
поплавки 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))...)
вы достигли пределов вашей платформы 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-битной OS 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
16.** 256 слишком большой для хранения в двойном поплавке точности. Я предлагаю вам запустить свой цикл для меньшего, например, диапазона (250), потому что большие значения k все равно не будут вносить вклад в первые сто цифр.
еще одна вещь, которую вы можете попробовать, это умножить на 16.*(- k) вместо деления на 16. * k. Это число будет округлено до нуля для большого k, поэтому не даст вам ошибок выполнения.
Я предлагаю вам использовать numpy.власть вместо**, это ручки переполняются лучше. Например, в вашем коде numpy.мощность(16., 256) будет оценивать inf, а деление конечного числа на inf дает ноль, что позволяет избежать ошибок во время выполнения, как и метод, предложенный в предыдущем абзаце.
Я использую python3.6 AMD64, я также встречаю эту проблему, это потому, что встроенный python float
является двойной точностью-float, это 64 бит,в большинстве задач прогаммирования 64 бит достаточно, но в некоторых дополнительных задачах этого недостаточно (например,scitific computing, Big data compute)