web-dev-qa-db-fra.com

Python calcul pi?

Je suis un débutant python et je veux calculer pi. J'ai essayé d'utiliser l'algorithme Chudnovsky parce que j'ai entendu dire qu'il était plus rapide que les autres algorithmes.

Voici mon code:

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)

Pour une raison quelconque, ce code donne la valeur de pi jusqu'à seulement 15 décimales par rapport à la valeur acceptable. J'ai essayé de résoudre ce problème en augmentant la valeur de précision; cela augmente le nombre de chiffres, mais seuls les 15 premiers sont toujours précis. J'ai essayé de changer la façon dont il calcule l'algorithme et cela n'a pas fonctionné non plus. Donc ma question est, y a-t-il quelque chose qui peut être fait pour ce code pour le rendre beaucoup plus précis ou devrais-je utiliser un autre algorithme? J'apprécierais de l'aide avec cela parce que je ne sais pas comment pour fonctionner avec autant de chiffres en python. Je voudrais pouvoir contrôler le nombre de chiffres (corrects) déterminés et affichés par le programme - que ce soit 10, 100, 1000, etc.

14
Norrin Rad

Il semble que vous perdiez de la précision dans cette ligne:

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

Essayez d'utiliser:

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

Cela se produit car même si Python peut gérer des entiers d'échelle arbitraires, il ne fonctionne pas aussi bien avec des flottants.

Bonus

Une implémentation sur une seule ligne utilisant un autre algorithme (la formule 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))
18
Juan Lopes

Pour les personnes qui viennent ici juste pour obtenir une solution prête à obtenir une précision arbitraire de pi avec 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()
8
Martin Thoma
from decimal import *

#Sets decimal to 25 digits of precision
getcontext().prec = 25

def factorial(n):
    if n<1:
        return 1
    else:
        return n * factorial(n-1)

def plouffBig(n): #http://en.wikipedia.org/wiki/Bailey%E2%80%93Borwein%E2%80%93Plouffe_formula
    pi = Decimal(0)
    k = 0
    while k < n:
        pi += (Decimal(1)/(16**k))*((Decimal(4)/(8*k+1))-(Decimal(2)/(8*k+4))-(Decimal(1)/(8*k+5))-(Decimal(1)/(8*k+6)))
        k += 1
    return pi

def bellardBig(n): #http://en.wikipedia.org/wiki/Bellard%27s_formula
    pi = Decimal(0)
    k = 0
    while k < n:
        pi += (Decimal(-1)**k/(1024**k))*( Decimal(256)/(10*k+1) + Decimal(1)/(10*k+9) - Decimal(64)/(10*k+3) - Decimal(32)/(4*k+1) - Decimal(4)/(10*k+5) - Decimal(4)/(10*k+7) -Decimal(1)/(4*k+3))
        k += 1
    pi = pi * 1/(2**6)
    return pi

def chudnovskyBig(n): #http://en.wikipedia.org/wiki/Chudnovsky_algorithm
    pi = Decimal(0)
    k = 0
    while k < n:
        pi += (Decimal(-1)**k)*(Decimal(factorial(6*k))/((factorial(k)**3)*(factorial(3*k)))* (13591409+545140134*k)/(640320**(3*k)))
        k += 1
    pi = pi * Decimal(10005).sqrt()/4270934400
    pi = pi**(-1)
    return pi
print "\t\t\t Plouff \t\t Bellard \t\t\t Chudnovsky"
for i in xrange(1,20):
    print "Iteration number ",i, " ", plouffBig(i), " " , bellardBig(i)," ", chudnovskyBig(i)
0
Kai Iyer