pi的计算,得到的价值与书

时间:2015-10-12 04:48:36

标签: python series pi

  

数学常数π(pi)是一个无理数,其值约为3.1415928 ...π的精确值等于下面的无穷和:π= 4/1 - 4/3 + 4/5 - 4 / 7 + 4/9 - 4/11 + ...我们可以通过计算前几个项的总和来得到π的良好近似值。编写一个函数approxPi(),它将浮点值误差作为参数,并通过计算上述和,逐项计算得出误差内的常数π,直到当前总和与前一个总和之差的绝对值(与少一个条款)不大于错误。一旦函数发现差异小于错误,它应该返回新的总和。请注意,此函数不应使用数学模块中的任何函数或常量。您应该使用所描述的算法来逼近π,而不是使用Python中的内置值。

我已经完成了以下程序,但出于某种原因,我从书中获得了不同的价值。

def pi(error):
    prev = 1
    current = 4
    i = 1
    while abs(current - prev) > error:
        d = 2.0* i +1
        sign = (-1)**i
        prev = current
        current = current + sign * 4 / d
        i = i +1
    return current

output In [2]: pi(0.01)
Out[2]: 3.146567747182955

但我需要获得此值

>>> approxPi(0.01)
3.1611986129870506
>>> approxPi(0.0000001)
3.1415928535897395

3 个答案:

答案 0 :(得分:3)

您使用的近似值在收敛时非常差,即您需要循环很多次才能获得合理的值。你看到差异将是1 / d,这就是准确性。您将需要循环5000次以获得4个数字50k次以获得下一个并获得500k以获得下一个等等(这是数字的指数时间复杂度)。

这可能是你在这里看到差异的原因之一,你只是得到了舍入错误加起来的情况。由于您需要使用那么多迭代,您将永远无法接近您正在使用的浮动的完整精度。另一个差异的来源是你的引用可能正在使用另一个退出条件,你的条件你应该得到一个小于提供的错误(理想情况下),你已经得到它(3.146567747182955-pi <0.01)。实际上,您的引用似乎正在使用条件abs(current-prev) > 4*error

你正在使用的公式是pi = 4arctan(1)并且使用arctan(x)的McLaurin扩展得到x的值,该值完全收敛。为了获得更好的性能,应该在该扩展中使用较低的x。例如,可以使用pi = 16arctan(1/5)-4arctan(1/239)(这给出了数字的线性时间复杂度):

def pi(error):
    a = 1.0/5
    b = 1.0/239

    prev = 1
    current = 0.0
    i = 0
    while abs(current - prev) > error:
        d = 2.0* i +1
        sign = (-1)**i
        prev = current
        current = current + sign * (16*a - 4*b)/d
        a = a*1.0/(5*5)
        b = b*1.0/(239*239) 
        i = i +1
    return current

答案 1 :(得分:0)

我猜你的函数和approxPi的停止规则是不同的。事实上,您的估计更好。如果打印出当前的所有值,您将看到当我等于50时,您的函数会产生您想要的输出。但是,它超越了这一点并产生了更好的近似值。

答案 2 :(得分:0)

因此,要获得您正在寻找的答案,那么所提出的问题在如何描述退出条件方面是错误的 重新组织你得到Pi = 4 *(1/1 + 1/3 + 1/5 + ...),得到3.1611986129870506,误差为0.01,然后你查看后续术语并在术语&lt;错误:

from itertools import count, cycle  #, izip for Py2
def approxPi(error):
    p = 0
    for sign, d in zip(cycle([1,-1]), count(1, 2)):  # izip for Py2
        n = sign / d
        p += n
        if abs(n) < error:
            break
    return 4*p

然后你得到正确答案:

>>> approxPi(0.01)
3.1611986129870506
>>> approxPi(0.0000001)
3.1415928535897395

使用您的代码(来自@PaulBoddington:Find the value of pi

def pi(error):
    prev = 0
    current = 1
    i = 1
    while abs(current - prev) > error:
        d = 2.0*i + 1
        sign = (-1)**i
        prev = current
        current = current + sign / d
        i += 1
    return 4*current

注意:这不是当前总和与前一个总和之间的差异,因此问题是错误的,但它等于difference_between_sums < error*4。因此,为了获得原始代码的正确退出,只需将误差乘以4,例如:

>>> pi(0.04)
3.1611986129870506