牛顿的方法:循环语句的顺序

时间:2016-05-16 19:53:52

标签: python loops debugging while-loop newtons-method

我正在尝试在Python中实现Newton的方法,但我在概念上理解了支票的位置问题。

重新审视牛顿方法,通过区分重复线性近似来近似根:

Newton's Method

我有以下代码:

# x_1 = x_0 - (f(x_0)/f'(x_0))
# x_n+1 - x_n = precision

def newton_method(f, f_p, prec=0.01):
    x=1
    x_p=1
    tmp=0

    while(True):
        tmp = x
        x = x_p - (f(x_p)/float(f_p(x_p)))
        if (abs(x-x_p) < prec):
            break;
        x_p = tmp

    return x

这是有效的,但是如果我将循环中的if语句移动到x_p = tmp行之后,该函数将停止按预期工作。像这样:

# x_1 = x_0 - (f(x_0)/f'(x_0))
# x_n+1 - x_n = precision

def newton_method(f, f_p, prec=0.01):
    x=1
    x_p=1
    tmp=0

    while(True):
        tmp = x
        x = x_p - (f(x_p)/float(f_p(x_p)))
        x_p = tmp
        if (abs(x-x_p) < prec):
            break;

    return x

为了澄清,函数v1(第一段代码)按预期工作,函数v2(第二段)没有。

为什么会这样?
原始版本不是基本上从2个作业中检查当前xx,而不是之前的x吗?

以下是我正在使用的测试代码:

def f(x):
    return x*x - 5

def f_p(x):
    return 2*x

newton_method(f,f_p)

修改

我最终使用了这个版本的代码,它放弃了tmp变量,对我来说更加清晰,概念上:

# x_1 = x_0 - (f(x_0)/f'(x_0))
# x_n+1 - x_n = precision

def newton_method(f, f_p, prec=0.01):
    x=1
    x_p=1
    tmp=0

    while(True):
        x = x_p - (f(x_p)/float(f_p(x_p)))
        if (abs(x-x_p) < prec):
            break;
        x_p = x

    return x

2 个答案:

答案 0 :(得分:2)

x[i]成为迭代中计算的新值。

版本1中发生了什么:

声明x = x_p - (f(x_p)/float(f_p(x_p)))转换为:

x[i] = x[i-2] - f(x[i-2])/f'(x[i-2]) - 1

但根据实际的数学公式,应该是这样的:

x[i] = x[i-1] - f(x[i-1])/f'(x[i-1])

同样,x[i-1] = x[i-2] - f(x[i-2])/f'(x[i-2]) - 2

比较 1 2 ,我们可以看到中的x[i]根据数学公式, 1 实际上是x[i-1]

这里要注意的要点是xx_p总是相隔一次。也就是说,xx_p的实际继承者,与看待代码时看起来不同。

因此,它按预期正常工作。

版本2中发生了什么:

就像上面的情况一样,同样的事情发生在x = x_p - (f(x_p)/float(f_p(x_p)))陈述中 但是当我们到达if (abs(x-x_p) < prec)时,x_p已将其值更改为temp = x = x[i-1]

但正如版本1中所推断的那样,x也是x[i-1]而不是x[i]

因此,abs(x - x_p)转换为abs(x[i-1] - x[i-1]),结果为0,从而终止迭代。

这里要注意的要点是,xx_p实际上是数字上相同的值,这总是导致算法在1次迭代后终止。

答案 1 :(得分:0)

<强>更新

这将保存x

的当前值
tmp = x

在此语句中,x的下一个值是从当前值x_p

创建的
x = x_p - (f(x_p)/float(f_p(x_p)))

如果收敛(例如下一个值 - 当前值&lt; threshold),则中断

if (abs(x-x_p) < prec):
    break;

将x_p设置为下一个迭代的值

x_p = tmp

如果你将x_p = tmp拉到if语句之上,那么你实际上是在2次迭代之前检查x vs x`,这不是你想要做的。这实际上会导致奇怪的行为,其中结果的正确性取决于起始值。如果你从x开始得到正确的答案,而如果从1开始,你就不会。

要测试它并查看原因,添加如下的打印声明会很有帮助。

def newton_method(f, f_p, prec=0.01):
    x=7
    x_p=1
    tmp=0

    while(True):
        tmp = x
        x = x_p - (f(x_p)/float(f_p(x_p)))
        print (x,x_p,_tmp)
        if (abs(x-x_p) < prec):
            break;
        x_p = tmp

您是否尝试从2次迭代前检查X vs X?或者来自循环的上一次迭代的X?

如果您在if语句之前有x_p=tmpif (abs(x-x_p) < prec):将检查x的当前值与之前版本的x,而不是之前2个分配中的x