牛顿求根的方法

时间:2019-02-03 21:47:04

标签: python numpy math newtons-method

我正在尝试实现牛顿方法来在Python中查找根。

预期结果是B点,但是Python返回了A点:

geogebra

代码:

import matplotlib.pyplot as plt
import numpy as np

def f(theta):
    return 1 - (((2 * 1.5) * np.sin(theta))/ 2.7)

def derivative(f, x):
    dx = 1E-8
    return (f(x + dx) - f(x)) / dx

def x_next(f, x_n):
    return 1 - (f(x_n) / derivative(f, x_n))

def newtons_method(f, x_n = 1, i = 0, max_iter = 100):
    i = i + 1
    if (i == max_iter):
        return None
    x_n = x_next(f, x_n)
    if (abs(f(x_n)) < 1E-4):
        return x_n
    print("i:",i,"x_n:",x_n,"f(x_n)",f(x_n))
    newtons_method(f, x_n, i, max_iter)

print(newtons_method(f))

1 个答案:

答案 0 :(得分:2)

您的主要问题出在您的例行x_next中。您有一个1,其中应该有一个x_n。所以例行程序应该是

def x_next(f, x_n):
    return x_n - (f(x_n) / derivative(f, x_n))

您的派生例程也很差。如果必须近似导数,则Newton-Raphson并不是最佳的使用方法。尽管使用的近似方法确实遵循导数的定义,但在数值上也不是很好。如果必须使用近似值,请使用

def derivative(f, x):
    dx = 1E-8
    return (f(x + dx) - f(x - dx)) / (2.0 * dx)

但是在这种情况下,导数非常容易直接计算。所以最好使用

def derivative(f, x):
    return -2 * 1.5 * np.cos(x) / 2.7

您也不会打印出根及其函数值的最终近似值-您将其计算出来并返回而不打印它。因此,请先放置您的print语句,然后再对其进行测试。

有了这些更改(加上注释掉了您从未使用过的matplotlib的导入),您的代码现在就可以了

#import matplotlib.pyplot as plt
import numpy as np

def f(theta):
    return 1 - (((2 * 1.5) * np.sin(theta))/ 2.7)

def derivative(f, x):
    return -2 * 1.5 * np.cos(x) / 2.7

def x_next(f, x_n):
    return x_n - (f(x_n) / derivative(f, x_n))

def newtons_method(f, x_n = 1, i = 0, max_iter = 100):
    i = i + 1
    if (i == max_iter):
        return None
    x_n = x_next(f, x_n)
    print("i:",i,"x_n:",x_n,"f(x_n)",f(x_n))
    if (abs(f(x_n)) < 1E-4):
        return x_n
    newtons_method(f, x_n, i, max_iter)

print(newtons_method(f))

结果只有两行

i: 1 x_n: 1.1083264212579311 f(x_n) 0.005607493777795347
i: 2 x_n: 1.1196379358595814 f(x_n) 6.373534192993802e-05

这就是您想要的。如果您坚持对导数使用数值逼近,请使用上面提供的版本,结果会略有不同:

i: 1 x_n: 1.10832642185337 f(x_n) 0.005607493482616466
i: 2 x_n: 1.1196379360265405 f(x_n) 6.373526104597182e-05