数学常数π(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
发布于 2015-10-12 05:28:04
你所使用的近似很难收敛,也就是说,你必须循环很多次才能得到一个合理的值。你看,差别是1/d,这就是精度。您必须循环5000次才能得到四位数,50 k次得到next,500 k得到next,等等(这是数字的指数时间复杂度)。
这可能是你在这里看到不一致的原因之一,你只是得到了四舍五入错误加起来的情况。因为您需要使用那么多的迭代,所以您将永远无法达到所使用的浮点数的全部精度。另一个不一致的原因是,您的引用可能使用了另一个退出条件,您的条件应该小于所提供的错误(理想情况下),并且得到了它(3.146567747182955-pi <0.0 1)。实际上,您的引用似乎使用的是条件abs(current-prev) > 4*error
。
您使用的公式是,pi=4arctan(1),并使用McLaurin展开的arctan(x)对x的值,这是在收敛的极限。为了获得更好的性能,应该在扩展中使用较低的x。例如,可以使用pi=16arctan(1/5)-4 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
发布于 2015-10-12 05:13:00
我想您的函数和approxPi的停止规则是不同的。事实上,你的估计更好。如果您打印出当前的所有值,您将看到,当i= 50时,您的函数将产生所需的输出。但是,它超越了这一点,产生了一个更好的近似。
发布于 2015-10-12 05:54:12
因此,为了得到你正在寻找的答案,提出的问题在描述退出条件方面是错误的。
重新组织得到Pi = 4*(1/1 + 1/3 + 1/5 +.),得到误差为0.01的3.1611986129870506,然后查看后面的项,并在术语< error时停止:
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
https://stackoverflow.com/questions/33073467
复制相似问题