Метод Ньютона для нахождения корней

Я пытаюсь реализовать метод Ньютона для поиска корней в Python.

Ожидаемый результат — точка B, но вместо этого Python возвращает точку A:

геогебра

Код:

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))

person snzm    schedule 03.02.2019    source источник


Ответы (1)


Ваша основная проблема заключается в вашей рутине x_next. У вас есть 1 вместо x_n. Так что рутина должна быть

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

Ваша производная программа также плоха. Если вам нужно аппроксимировать производную, метод Ньютона-Рафсона — не лучший вариант. Ваш метод аппроксимации, который вы используете, также не очень хорош в численном отношении, хотя он соответствует определению производной. Если вы должны использовать приближение, используйте

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
person Rory Daulton    schedule 03.02.2019