Python:尽可能有效地估计具有trig函数的Pi

时间:2016-11-27 21:26:13

标签: python python-3.x trigonometry

我有一个任务,我需要以计算有效的方式近似Pi。这是我的策略:我使用单位圆,等角三角形的角平分线,以及罪的定义。我画了一张图:

enter image description here

例如,如果我想使用六边形(6点/ 6边),我只需要计算a :( 0.5*sin(2*pi/2*x)并将其乘以(2*x) 。最后,从Pi = Circumference/Diameter开始,然后我的近似值Pi =多边形周长(从Diameter = 1开始)。

本质:

from math import sin, pi
def computePi(x):    #x: number of points desired
    p = x*sin(pi/x)
    print(p)

computePi(10000)
3.141592601912665

它有效,而且我觉得它有效率,不是吗?谢谢你的时间!

编辑:为了避免循环,我使用阿基米德算法仅使用毕达哥拉斯理论来重新编写:

enter image description here

代码:

from math import sqrt

def approxPi(x):                  #x: number of times you want to recursively apply Archmidedes' algorithm
    s = 1                         #Unit circle
    a = None; b = None;   
    for i in range(x):
        a = sqrt(1 - (s/2)**2)
        b = 1 - a
        print('The approximate value of Pi using a {:5g}-sided polygon is {:1.8f}'.format(6*2**(i),(s*6*2**(i))/2))
        s = sqrt(b**2 + (s/2)**2)

3 个答案:

答案 0 :(得分:5)

更好的是

print(4 * math.atan(1))

这在计算中没有以任何明显的方式使用pi(尽管@ Jean-FrançoisFabre注释,pi可能在函数定义中使用),除了trig函数之外,它只有一个简单的乘法。当然,还有

print(2 * math.acos(0))

print(2 * math.asin(1))

答案 1 :(得分:2)

尽管不是非常有效的解决方案,但使用Euler的Basel Problem解决方案是有趣的:

from math import sqrt

def psum(n):
    return sum(1/k**2 for k in range(1,n+1))

def approxPi(n):
    s = psum(n)
    return sqrt(6*s)

例如,

>>> approxPi(100000)
3.141583104326456

正如我所说,效率不高。另一方面,显然没有微妙的循环性。众所周知,许多其他系列会聚到pi或收敛到可以轻松计算pi的值,而其他许多系列会更快收敛。

编辑:@Simon关于使用Gauss-Legendre algorithm和模块decimal的建议会导致以下代码(返回结果)作为一个字符串):

import decimal
from decimal import Decimal as d

def approxPi(n):
    eps = 1/d(10**n)
    decimal.getcontext().prec = 3*n #probably overkill, but need room for products
    a = d(1)
    b = 1/d(2).sqrt()
    t = 1/d(4)
    p = d(1)
    dif = a-b
    if dif < 0: dif = -dif
    i = 1
    while dif >= eps:
        a1 = (a+b)/2
        b1 = a*b
        b1 = b1.sqrt()
        t1 = t - p*(a - a1)**2
        p1 = 2*p
        a,b,t,p = a1,b1,t1,p1
        dif = a1-b1
        if dif < 0: dif = -dif
    pi = (a + b)**2/(4*t)
    return str(pi)[:n+2]

例如,

>>> approxPi(1000)
'3.1415926535897932384626433832795028841971693993751058209749445923078164062862089986280348253421170679821480865132823066470938446095505822317253594081284811174502841027019385211055596446229489549303819644288109756659334461284756482337867831652712019091456485669234603486104543266482133936072602491412737245870066063155881748815209209628292540917153643678925903600113305305488204665213841469519415116094330572703657595919530921861173819326117931051185480744623799627495673518857527248912279381830119491298336733624406566430860213949463952247371907021798609437027705392171762931767523846748184676694051320005681271452635608277857713427577896091736371787214684409012249534301465495853710507922796892589235420199561121290219608640344181598136297747713099605187072113499999983729780499510597317328160963185950244594553469083026425223082533446850352619311881710100031378387528865875332083814206171776691473035982534904287554687311595628638823537875937519577818577805321712268066130019278766111959092164201989'

同意this

以上不到一秒钟。 10,000秒需要几秒钟。看看用Python获取1,000,000个数字需要多长时间会很有趣。

答案 2 :(得分:1)

以下是您的问题的代码:

from math import radians, sin


def computePi(n):
    p = n * (sin(radians((360/(2*n)))))
    print(p)
computePi(1000)

此代码背后的理论解释如下:https://math.stackexchange.com/questions/588141/how-is-the-value-of-pi-pi-actually-calculated