Python pi 计算?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/28284996/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Python pi calculation?
提问by Norrin Rad
I am a python beginner and I want to calculate pi. I tried using the Chudnovsky algorithm because I heard that it is faster than other algorithms.
我是一个python初学者,我想计算pi。我尝试使用 Chudnovsky 算法,因为我听说它比其他算法更快。
This is my 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)
For some reason this code yields the vakue of pi up to only 15 decimals as compared with the acceptable value. I tried to solve this by increasing the precision value; this increases the number of digits, but only the first 15 are still accurate. I tried changing the way it calculates the algorithm and it didn't work either. So my question is, is there something that can be done to this code to make it much more accurate or would I have to use another algorithm?I would appreciate help with this because I don't know how to operate with so many digits in python. I would like to be able to control the number of (correct) digits determined and displayed by the program -- whether 10, 100, 1000, etc.
出于某种原因,与可接受的值相比,此代码产生的 pi 值最多只有 15 位小数。我试图通过增加精度值来解决这个问题;这增加了位数,但只有前 15 位仍然准确。我尝试改变它计算算法的方式,但也没有用。所以我的问题是,是否可以对此代码进行一些操作以使其更加准确,或者我是否必须使用其他算法?我很感激这方面的帮助,因为我不知道如何在 python 中处理这么多数字。我希望能够控制程序确定和显示的(正确)位数——无论是 10、100、1000 等。
采纳答案by Juan Lopes
It seems you are losing precision in this line:
看来您在这一行中失去了精度:
pi = pi * Decimal(12)/Decimal(640320**(1.5))
Try using:
尝试使用:
pi = pi * Decimal(12)/Decimal(640320**Decimal(1.5))
This happens because even though Python can handle arbitrary scale integers, it doesn't do so well with floats.
发生这种情况是因为即使 Python 可以处理任意比例的整数,但它对浮点数的处理效果不佳。
Bonus
奖金
A single line implementation using another algorithm (the BBP formula):
使用另一种算法(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))
回答by Martin Thoma
For people who come here just to get a ready solution to get arbitrary precision of pi with Python (sourcewith a couple of edits):
对于来这里只是为了获得一个现成的解决方案来使用 Python 获得任意精度的 pi 的人(经过一些编辑的源代码):
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()
回答by Kai Iyer
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)