Расчет Питона пи?

Я новичок в Python и хочу вычислить число Пи. Я попробовал использовать алгоритм Чудновского, потому что слышал, что он быстрее других алгоритмов.

Это мой код:

from math import factorial
from decimal import Decimal, getcontext

getcontext().prec=100

def calc(n):
    t= Decimal(0)
    pi = Decimal(0)
    deno= Decimal(0)
    k = 0
    for k in range(n):
        t = ((-1)**k)*(factorial(6*k))*(13591409+545140134*k)
        deno = factorial(3*k)*(factorial(k)**3)*(640320**(3*k))
        pi += Decimal(t)/Decimal(deno)                                   
    pi = pi * Decimal(12)/Decimal(640320**(1.5))
    pi = 1/pi
    return pi

print calc(25)

По какой-то причине этот код дает значение числа пи всего до 15 знаков после запятой по сравнению с допустимым значением. Я попытался решить эту проблему, увеличив значение точности; это увеличивает количество цифр, но только первые 15 по-прежнему точны. Я попытался изменить способ вычисления алгоритма, и это тоже не сработало. Итак, мой вопрос: можно ли что-то сделать с этим кодом, чтобы сделать его более точным, или мне придется использовать другой алгоритм? Я был бы признателен за помощь в этом, потому что я не знаю, как это сделать. работать с таким количеством цифр в питоне. Я хотел бы иметь возможность контролировать количество (правильных) цифр, определенных и отображаемых программой, будь то 10, 100, 1000 и т. Д.


person Norrin Rad    schedule 02.02.2015    source источник
comment
Просто для сравнения, вот немного рабочего кода Чудновского: craig-wood.com/nick /articles/pi-chudnovsky   -  person runDOSrun    schedule 02.02.2015
comment
Точность ограничена точностью по умолчанию десятичного пакета в Python. Настройте его правильно и все будет хорошо. См. docs.python.org/3/library/decimal.html.   -  person 4dummies    schedule 07.10.2018


Ответы (2)


Кажется, вы теряете точность в этой строке:

pi = pi * Decimal(12)/Decimal(640320**(1.5))

Попробуйте использовать:

pi = pi * Decimal(12)/Decimal(640320**Decimal(1.5))

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

Бонус

Однострочная реализация с использованием другого алгоритма (формула BBP):

from decimal import Decimal, getcontext
getcontext().prec=100
print sum(1/Decimal(16)**k * 
          (Decimal(4)/(8*k+1) - 
           Decimal(2)/(8*k+4) - 
           Decimal(1)/(8*k+5) -
           Decimal(1)/(8*k+6)) for k in range(100))
person Juan Lopes    schedule 02.02.2015
comment
Большое спасибо! Это сработало. Для меня невероятно, как такое небольшое изменение имело значение. - person Norrin Rad; 02.02.2015
comment
@Juan Lopes Привет, не могли бы вы помочь мне написать псевдокод для этой формулы BBP для расчета PI - person Sumit Khanduri; 27.07.2017
comment
Никто еще не указывал на это, но формула BBP — это алгоритм вставки, который работает в шестнадцатеричном, а не в десятичном виде, верно? Я цитирую википедию по этому поводу - person Jeff; 14.04.2021

Для людей, которые приходят сюда только для того, чтобы получить готовое решение для получения произвольной точности пи с помощью Python (исходник с парой правок):

import decimal

def pi():
    """
    Compute Pi to the current precision.

    Examples
    --------
    >>> print(pi())
    3.141592653589793238462643383

    Notes
    -----
    Taken from https://docs.python.org/3/library/decimal.html#recipes
    """
    decimal.getcontext().prec += 2  # extra digits for intermediate steps
    three = decimal.Decimal(3)      # substitute "three=3.0" for regular floats
    lasts, t, s, n, na, d, da = 0, three, 3, 1, 0, 0, 24
    while s != lasts:
        lasts = s
        n, na = n + na, na + 8
        d, da = d + da, da + 32
        t = (t * n) / d
        s += t
    decimal.getcontext().prec -= 2
    return +s               # unary plus applies the new precision

decimal.getcontext().prec = 1000
pi = pi()
person Martin Thoma    schedule 03.05.2017
comment
Этот код присутствует в документации библиотеки Python для decimal. - person ShreevatsaR; 06.12.2018