【问题标题】:Newton's method: order of statements in loop牛顿法:循环中的语句顺序
【发布时间】:2016-09-12 17:31:30
【问题描述】:

我正在尝试在 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

【问题讨论】:

  • the function ceases to work as expected.: 究竟如何?
  • 例如,当试图将解近似为 x^2 - 5 时,而不是用前者得到 2.236-ish,而用后者得到 3.0。

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


【解决方案1】:

更新

这会保存 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=tmpif (abs(x-x_p) &lt; prec): 将检查 x 的当前值与 x 的先前版本,而不是 2 次分配前的 x

【讨论】:

  • 好的。所以它确实是从之前的两个作业中检查 x 。但是,为什么从之前的一项作业中检查 x 会导致算法失败?这基本上是我的问题。
  • 更新了问题以进一步澄清我的问题的性质
【解决方案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

比较12,我们可以看到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) &lt; 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 次迭代后终止。

【讨论】:

  • 对不起,我应该澄清一下。我发布的代码,据我了解,它与两次迭代前的 x 相比,似乎按我的预期工作,而之后的 if 语句似乎工作不正确。为什么是这样?我将更新问题以帮助解释
  • 让我感到困惑的是 x[i-2] 版本似乎是有效的,而 x[i-1] 版本却没有。
  • @Aristides 更新了答案!希望这次是清楚的!
  • 好多了,但是我仍然没有点击。为什么x[i]实际上是x[i-1]在第一个版本中?
  • 实际上x[i] 在两个版本中都是x[i-1]。如果是x = x - (f(x)/float(f_p(x))),它确实是x[i]。无论如何,不​​要太认真地对待指数的绝对值。我刚刚介绍了它们以建立变量之间的顺序。他们的区别才是最重要的。
猜你喜欢
  • 2017-04-10
  • 1970-01-01
  • 2013-10-24
  • 2019-06-19
  • 2015-01-06
  • 2018-07-30
  • 2013-10-17
  • 2017-05-05
相关资源
最近更新 更多