在误差范围内近似π

2 投票
3 回答
5726 浏览
提问于 2025-04-17 15:27

首先,问题是这样的。

数学常数 π(读作“派”)是一个无理数,值大约是 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 个回答

1

这是我会这样做的:

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)
1

这里有几个问题:

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

如果你想用那个公式来近似计算圆周率π,首先可以写出几个项:

π = 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

撰写回答