重要修改:
谁认为这个近似值可以得到圆周率——引用自
维基百科:
它收敛相当慢,经过500,000项之后,只能产生5位正确的小数点π。
原回答:
这是一个教育性的例子。您尝试使用快捷方式,并尝试通过在同一迭代中处理
k
的两个步骤来实现“振荡”符号。然而,您每次迭代只调整了一个步骤的
k
。
通常,在数学中至少可以通过
(-1)**i
来实现振荡符号。因此,我选择了这个更易读的实现方式:
def pi_approx(num_iterations):
k = 3.0
s = 1.0
for i in range(num_iterations):
s = s-((1/k) * (-1)**i)
k += 2
return 4 * s
您可以看到,我稍微改变了您的方法,以提高可读性。 您无需在while循环中检查num
,也没有特别需要使用pi
变量。 您的est
实际上是一个逐步增加的总和,那么为什么不将其命名为s
("sum"是Python中的内置关键字)。 最后乘以4
,按照您的公式计算即可。
测试:
>>> pi_approx(100)
3.1514934010709914
然而,收敛并不特别好:
>>> pi_approx(100) - math.pi
0.009900747481198291
你的期望输出有些不可靠,因为你的
piApprox(300)
(根据你的说法应该是
3.13825932952
)离π值太远了。你是怎么想到这个数值的?这可能受到累积数值误差的影响吗?
编辑
我不太信任书中关于函数在10次和300次迭代后应返回什么的描述。实际上,在10步之后,中间结果应该相当自由地处理数值误差。事实上,这里是否同时使用两个
k
步骤会有所不同。因此,这很可能是我
pi_approx(10)
和书中结果之间的区别。对于300次迭代,数值误差可能会严重影响书中的结果。如果这是一本旧书,并且他们在C语言中实现了他们的示例,可能使用单精度,那么结果的相当一部分可能是由于数值误差的累积造成的(注意:这是一个数值误差如何影响你的极端案例:小数值和大数值的重复总和,它不会更糟!)。
重要的是,您已经查看了数学内容(PI公式),并实现了一个工作的Python版本来近似该公式。这是本书的学习目标,所以继续解决下一个问题吧:-)。
piApprox(2)
的输出结果为3.466666666666667
。 - user4511836piApprox(300)
应该返回3.13825932952
吗?因为那不是 PI。然而,如果正确实现了公式,它是可行的。 - Dr. Jan-Philip Gehrcke