在误差范围内近似π
首先,问题是这样的。
数学常数 π(读作“派”)是一个无理数,值大约是 3.1415928... π 的准确值可以通过下面这个无限的加法公式来表示:π = 4/1 - 4/3 + 4/5 - 4/7 + 4/9 - 4/11 + ... 我们可以通过计算前几项的和来得到 π 的一个不错的近似值。你需要写一个名为 approxPi() 的函数,它接受一个浮点数参数 error,并通过逐项计算上面的和来在误差范围内近似 π,直到当前和与前一个和(少一项)之间的绝对差值不大于 error。一旦函数发现差值小于 error,就应该返回新的和。请注意,这个函数不能使用数学模块中的任何函数或常量。你需要使用描述的算法来近似 π,而不是直接使用 Python 中的内置值。
如果有人能帮我理解这个问题在问什么,我会非常感激,因为我读了很多遍,但仍然无法完全理解它的意思。我翻阅了我的教科书,发现了一个类似的问题,是关于用 e 的无限和来近似 e:1/0! + 1/1! + 1/2! + 1/3! + ...
def approxE(error):
import math
'returns approximation of e within error'
prev = 1 # approximation 0
current = 2 # approximation 1
i = 2 # index of next approximation
while current-prev > error:
#while difference between current and previous
#approximation is too large
#current approximation
prev = current #becomes previous
#compute new approximation
current = prev + 1/math.factorial(i) # based on index i
i += 1 #index of next approximation
return current
我试着让我的程序模仿这个,但我觉得离解决方案还很远。
def approxPi(error):
'float ==> float, returns approximation of pi within error'
#π = 4/1 - 4/3 + 4/5 - 4/7 + 4/9 - 4/11 + ...
prev = 4 # 4/1 = 4 : approx 0
current = 2.6666 # 4/1 - 4/3 = 2.6666 : approx 1
i = 5 # index of next approx is 5
while current-prev > error:
prev = current
current = prev +- 1/i
i = i +- 2
return current
成功的程序应该返回
approxPi(0.5) = 3.3396825396825403 和 approxPi(0.05) = 3.1659792728432157
再次感谢任何帮助。我想知道我在这方面做错了什么。
3 个回答
这是我会这样做的:
def approxPi(error):
# pi = 4/1 - 4/3 + 4/5 - 4/7 + 4/9 - 4/11 + ...
value = 0.0
term = 1.0e6
i = 1
sign = 1
while fabs(term) > error:
term = sign/i
value += term
sign *= -1
i += 2
return 4.0*value
print approxPi(1.0e-5)
这里有几个问题:
A) i = i +- 2
这个写法并不是你想的那样,具体它是什么我也不太清楚。
正确的写法应该是这样的(有很多种方式):
if i < 0:
i = -(i-2)
else:
i = -(i+2)
同样的情况也适用于:
current = prev +- 1/i
应该是:
current = prev + 4.0/i
或者其他的写法,这取决于 i
里到底存了什么。要小心!在 python2 中,除非你从未来导入新的除法功能,否则你必须写 4.0
,不能只写 4
。
我个人更喜欢用两个变量,一个是除数的绝对值,另一个是符号,这样在每次循环时:
current = current + sign * 4 / d
d += 2
sign *= -1
这样看起来好多了!
B) 循环结束时应该检查误差的绝对值:
像这样:
while abs(current-prev) > error:
因为当前值会在目标值的上下跳动,一个值比目标大,一个值比目标小,所以一个误差是正的,一个是负的。
如果你想用那个公式来近似计算圆周率π,首先可以写出几个项:
π = 4/1 - 4/3 + 4/5 - 4/7 + 4/9 - 4/11 + ...
0 1 2 3 4 5 ...
然后写一个函数,返回这个公式的第n项:
def nth_term(n):
return 4 / (2.0 * n + 1) * (-1) ** n
接下来,代码就比较通用了:
def approximate_pi(error):
prev = nth_term(0) # First term
current = nth_term(0) + nth_term(1) # First + second terms
n = 2 # Starts at third term
while abs(prev - current) > error:
prev = current
current += nth_term(n)
n += 1
return current
对我来说,这个方法似乎有效:
>>> approximate_pi(0.000001)
3.1415929035895926