0
pi/2 = 1 + 1/3 + (1*2) / (3*5) + (1*2*3) / (3*5*7) + ...

好的,让我们再试一次。

我需要编写一个函数,它将最大误差作为 pi 的值的参数,并返回计算出的 pi 值以及到达该点所需的迭代次数。我不能使用递归算法。

到目前为止,我有:

def piEuler (x):
    count = 0.0
    approx = 0.0
    approx2 = 1.0
    error = math.pi/2 - approx2
    while error > x:
        count = count + 1
        approx3 = approx + approx2
        error = math.pi/2 - approx3
        #print error
        approx = approx + approx2
        approx2 = approx2 * count/(count + 2)
        #print approx2
    final = math.pi - error
    return final, count

问题是程序返回负值。误差应该收敛到零。我需要能够从 pi 的接受值中减去我的错误,以从系列中获得近似值。我究竟做错了什么?

4

3 回答 3

2

这有效:

import math

def piEuler(x):

    halfpi    = math.pi / 2.0
    count     = 0
    approx    = 1.0
    divisor   = 1
    numerator = 1
    while True:
        count     += 1
        numerator *= count
        divisor   *= 2*count + 1
        approx    += float(numerator) / float(divisor)
        error      = halfpi - approx

        if error < x:
            return (math.pi - error), count

基本区别是:

  1. 通过将循环的终止条件切换为测试/中断,我可以删除系列第二项的手动计算
  2. 小心使用 int 和 float 数据类型(这可能是您的问题)
  3. 更好的变量命名导致更容易调试
于 2013-02-22T03:54:21.550 回答
1

看起来你错误地实现了算法。而不是做pi/2 = 1 + 1/3 + (1*2)/(3*5) + (1*2*3)/(3*5*7) + ...,它看起来像你的代码在做pi/2 = 1 + 1/3 + (1*2)/(3*4) + (1*2*3)/(3*4*5) + ...

由于分母最终会变小,因此您将总和增加更多,无疑会导致超调并因此产生负误差。

问题出在这一行:

approx2 = approx2 * count/(count + 2)

如您所见,何时count是偶数,count + 2将是偶数。一个简单的解决方法是将其更改为:

approx2 = approx2 * count/(2 * count + 1)

这是一个有效的示例算法,但使用术语之间的相对误差而不是绝对误差(不想放弃一切;)):

from __future__ import division

def half_pi(max_err=10**-6, max_iter=10000):
    partial_sum = cur_term = 1
    n = 1
    while abs(t) > max_err and n < max_iter:
        cur_term = cur_term * (n / (2 * n + 1))
        partial_sum += cur_term
        n += 1
    return partial_sum, n
于 2013-02-22T04:06:31.583 回答
0

您应该尝试重写例程,以使序列中的最小项(代码中的approx2)必须大于错误。

在你最后的错误计算中你也有'math.pi'。它必须是 math.pi/2 吗?

似乎错误的性质也在波动!

于 2013-02-22T04:03:09.647 回答