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)