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.
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))
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()
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)