所以我必须用以下方式近似Pi:4 *(1-1 / 3 + 1 / 5-1 / 7 + 1/9 -...)。它也应该基于迭代次数。所以函数应该是这样的:
>>> piApprox(1)
4.0
>>> piApprox(10)
3.04183961893
>>> piApprox(300)
3.13825932952
但它的工作原理如下:
>>> piApprox(1)
4.0
>>> piApprox(10)
2.8571428571428577
>>> piApprox(300)
2.673322240709928
我做错了什么?这是代码:
def piApprox(num):
pi=4.0
k=1.0
est=1.0
while 1<num:
k+=2
est=est-(1/k)+1/(k+2)
num=num-1
return pi*est
答案 0 :(得分:2)
这就是你的计算方法:
4*(1-1/3+1/5-1/5+1/7-1/7+1/9...)
您可以通过在循环结束时添加k += 2
来修复它:
def piApprox(num):
pi=4.0
k=1.0
est=1.0
while 1<num:
k+=2
est=est-(1/k)+1/(k+2)
num=num-1
k+=2
return pi*est
此外,您计算迭代次数的方式也是错误的,因为您当时正在添加两个元素。
这是一个更干净的版本,它返回您期望的10次和300次迭代的输出:
def approximate_pi(rank):
value = 0
for k in xrange(1, 2*rank+1, 2):
sign = -(k % 4 - 2)
value += float(sign) / k
return 4 * value
这是相同的代码,但更紧凑:
def approximate_pi(rank):
return 4 * sum(-float(k%4 - 2) / k for k in xrange(1, 2*rank+1, 2))
答案 1 :(得分:1)
重要编辑: 谁希望这种近似产生PI - 引自Wikipedia:
然而,它收敛得非常缓慢 - 在产生500,000个术语之后 只有五个正确的十进制数字π
原始回答:
这是一个教育的例子。您尝试使用快捷方式并尝试通过在同一次迭代中处理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
应该离PI太远了。你是怎么想出来的?这可能会受到累积数值误差的影响吗?
修改强>
对于在10次和300次迭代后函数应返回的内容,我不太相信这本书。事实上,在10个步骤之后,中间结果应该没有数值误差。在那里,你是否同时采取两个k
步骤确实有所不同。所以这很可能是我的pi_approx(10)
和书籍之间的差异。对于300次迭代,数值误差可能严重影响了本书的结果。如果这是一本旧书,并且他们已经在C中实现了他们的例子,可能使用单精度,那么结果的很大一部分可能是由于数值误差的累积(注意:这是你可能有多糟糕的一个主要例子)受数值误差的影响:小值和大值的重复和,它不会变得更糟!)。
重要的是你已经查看了数学(PI的公式),并且你已经实现了一个近似于该公式的工作Python版本。这是本书的学习目标,所以继续解决下一个问题: - )。
答案 2 :(得分:0)
def piApprox(num):
pi=4.0
k=3.0
est=1.0
while 1<num:
est=est-(1/k)+1/(k+2)
num=num-1
k+=4
return pi*est
也适用于实际任务使用math.pi
答案 3 :(得分:0)
这是一个稍微简单的版本:
def pi_approx(num_terms):
sign = 1. # +1. or -1.
pi_by_4 = 1. # first term
for div in range(3, 2 * num_terms, 2): # 3, 5, 7, ...
sign = -sign # flip sign
pi_by_4 += sign / div # add next term
return 4. * pi_by_4
给出了
>>> for n in [1, 10, 300, 1000, 3000]:
... print(pi_approx(n))
4.0
3.0418396189294032
3.1382593295155914
3.140592653839794
3.1412593202657186
答案 4 :(得分:0)
尽管所有这些答案都是非常好的近似值,但是如果您使用的是Madhava-Leibniz系列,则比您应该得出的结果要大得多,根据该网站,“在第21个词条中,π正确近似为11位小数,即3.14159265359” :https://en.wikipedia.org/wiki/Approximations_of_%CF%80
因此,更精确的解决方案可能是对此进行任何更改:
import math
def estimate_pi(terms):
ans = 0.0
for k in range(terms):
ans += (-1.0/3.0)**k/(2.0*k+1.0)
return math.sqrt(12)*ans
print(estimate_pi(21))
输出:3.141592653595635