牛顿法:循环语句的顺序
Newton's method: order of statements in loop
我正在尝试在 Python 中实现牛顿法以获得乐趣,但我在概念上理解支票的位置时遇到了问题。
重温牛顿法作为一种通过微分重复线性逼近来逼近根的方法:
我有以下代码:
# 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(第二段)没有。
为什么会这样?
原始版本本质上不是检查当前的 x
与 2 个作业中的 x
,而不是紧邻的前一个 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
更新
这保存了x的当前值
tmp = x
在此语句中,x 的下一个值是根据当前值创建的 x_p
x = x_p - (f(x_p)/float(f_p(x_p)))
如果收敛(例如下一个值-当前值<阈值),中断
if (abs(x-x_p) < prec):
break;
将x_p设置为下一次迭代的值
x_p = tmp
如果您将 x_p = tmp
拉到 if 语句上方,您实际上是在检查 2 次迭代前的 x
与 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 与 X?还是来自上一次循环迭代的 X?
如果在 if 语句之前有 x_p=tmp
,if (abs(x-x_p) < prec):
将检查 x 的当前值与之前版本的 x,而不是来自 2 次赋值之前的 x
让 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,我们可以看到1中的x[i]
根据数学公式实际上是x[i-1]
。
这里要注意的要点是 x
和 x_p
始终相隔一次迭代。也就是说,x
是 x_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,因此终止迭代。
这里要注意的要点是 x
和 x_p
在数值上实际上是相同的值,这总是导致算法本身仅在 1 次迭代后终止。
我正在尝试在 Python 中实现牛顿法以获得乐趣,但我在概念上理解支票的位置时遇到了问题。
重温牛顿法作为一种通过微分重复线性逼近来逼近根的方法:
我有以下代码:
# 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(第二段)没有。
为什么会这样?
原始版本本质上不是检查当前的 x
与 2 个作业中的 x
,而不是紧邻的前一个 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
更新
这保存了x的当前值
tmp = x
在此语句中,x 的下一个值是根据当前值创建的 x_p
x = x_p - (f(x_p)/float(f_p(x_p)))
如果收敛(例如下一个值-当前值<阈值),中断
if (abs(x-x_p) < prec):
break;
将x_p设置为下一次迭代的值
x_p = tmp
如果您将 x_p = tmp
拉到 if 语句上方,您实际上是在检查 2 次迭代前的 x
与 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 与 X?还是来自上一次循环迭代的 X?
如果在 if 语句之前有 x_p=tmp
,if (abs(x-x_p) < prec):
将检查 x 的当前值与之前版本的 x,而不是来自 2 次赋值之前的 x
让 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,我们可以看到1中的x[i]
根据数学公式实际上是x[i-1]
。
这里要注意的要点是 x
和 x_p
始终相隔一次迭代。也就是说,x
是 x_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,因此终止迭代。
这里要注意的要点是 x
和 x_p
在数值上实际上是相同的值,这总是导致算法本身仅在 1 次迭代后终止。