Визуализация метода Ньютона
Метод
Ньютона (метод касательных) применяется
в том случае, если уравнение f(x)
= 0 имеет
корень
,
и выполняются условия:
1)
функция y= f(x) определена
и непрерывна при
;
2) f(a)·f(b) < 0 (функция принимает значения разных знаков на концах отрезка [a;b]);
3) производные f'(x) и f''(x) сохраняют знак на отрезке [a;b] (т.е. функция f(x) либо возрастает, либо убывает на отрезке [a;b], сохраняя при этом направление выпуклости);
4)
.
Основная идея метода заключается в следующем: на отрезке [a;b] выбирается такое число x0, при котором f(x0) имеет тот же знак, что и f''(x0), т. е. выполняется условие f(x0)·f''(x) > 0. Таким образом, выбирается точка с абсциссой x0, в которой касательная к кривой y=f(x) на отрезке [a;b] пересекает ось Ox. За точку x0 сначала удобно выбирать один из концов отрезка.
Рассмотрим метод Ньютона на конкретном примере.
Пусть нам дана возрастающая функция y = f(x) =x2-2, непрерывная на отрезке (0;2), и имеющая f '(x) = 2x > 0 и f ''(x) = 2 > 0.
Рисунок 1. f(x) =x2-2
Уравнение касательной в общем виде имеет представление:
y-y0= f '(x0)·(x-x0).
В нашем случае: y-y0=2x0·(x-x0). В качестве точки x0 выбираем точку B1(b; f(b)) = (2,2). Проводим касательную к функции y = f(x)в точке B1, и обозначаем точку пересечения касательной и оси Ox точкой x1. Получаем уравнение первой касательной:y-2=2·2(x-2), y=4x-6.
Точка
пересечения касательной и оси Ox:
x1 =
Рисунок 2. Результат первой итерации
Затем находим точку пересечения функции y=f(x) и перпендикуляра, проведенного к оси Ox через точку x1, получаем точку В2 =(1.5; 0.25). Снова проводим касательную к функции y = f(x) в точке В2, и обозначаем точку пересечения касательной и оси Oxточкой x2.
Уравнение второй касательной: y-2.25=2*1.5(x-1.5), y = 3x – 4.25.
Точка
пересечения касательной и оси Ox:
x2 =
.
Рисунок 3. Вторая итерация метода Ньютона
Затем находим точку пересечения функции y=f(x) и перпендикуляра, проведенного к оси Ox через точку x2, получаем точку В3 и так далее.
В3
= (
)
Рисунок 4. Третий шаг метода касательных
Первое приближение корня определяется по формуле:
=
1.5.
Второе приближение корня определяется по формуле:
=
Третье приближение корня определяется по формуле:
Таким образом, i-ое приближение корня определяется по формуле:
Вычисления ведутся до тех пор, пока не будет достигнуто совпадение десятичных знаков, которые необходимы в ответе, или заданной точности e - до выполнения неравенства |xi-xi-1| < e.
В нашем случае, сравним приближение, полученное на третьем шаге с реальным ответом, посчитанном на калькуляторе:
Рисунок 5. Корень из 2, посчитанный на калькуляторе
.
Как видно, уже на третьем шаге мы получили погрешность меньше 0.000002.
Таким образом можно вычислить значение величины "корень квадратный из 2" с любой степенью точности. Этот замечательный метод был изобретен Ньютоном и позволяет находить корни очень сложных уравнений.
Метод Ньютона: приложение на С++
В данной статье мы автоматизируем процесс вычисления корней уравнений, написав консольное приложение на языке C++. Разрабатывать его мы будем в Visual C++ 2010 Express, это бесплатная и очень удобная среда разработки С++.
Для начала запустим Visual C++ 2010 Express. Появится стартовое окно программы. В левом углу нажмем «Создать проект».
Рис. 1. Начальная страница Visual C++ 2010 Express
В появившемся меню выберем «Консольное приложение Win32», введем имя приложение «Метод_Ньютона».
Рис. 2. Создание проекта
В появившемся окно жмем «Готово». Далее появится окно, содержащее текстовый редактор кода для файла Метод_Ньютона.cpp.
Рис. 3. Редактор кода
Далее приведен подробный листинг Метода Ньютона:
// Метод_Ньютона.cpp: определяет точку входа для консольного приложения #include "stdafx.h" #include <iostream> using namespace std; float f(double x) //возвращает значение функции f(x) = x^2-2 { return x*x-2; } float df(float x) //возвращает значение производной { return 2*x; } float d2f(float x) // значение второй производной { return 2; } int _tmain(int argc, _TCHAR* argv[]) { int exit = 0, i=0;//переменные для выхода и цикла double x0,xn;// вычисляемые приближения для корня double a, b, eps;// границы отрезка и необходимая точность do { i=0; cout<<"Please input [a;b]\n=>"; cin>>a>>b; // вводим границы отрезка, на котором будем искать корень cout<<"\nPlease input epsilon\n=>"; cin>>eps; // вводим нужную точность вычислений if (a > b) // если пользователь перепутал границы отрезка, меняем их местами { x0 = a; a = b; b = x0; } if (f(a)*f(b)>0) // если знаки функции на краях отрезка одинаковые, то здесь нет корня cout<<"\nError! No roots in this interval\n"; else { if (f(a)*d2f(a)>0) x0 = a; // для выбора начальной точки проверяем f(x0)*d2f(x0)>0 ? else x0 = b; xn = x0-f(x0)/df(x0); // считаем первое приближение cout<<++i<<"-th iteration = "<<xn<<"\n"; while(fabs(x0-xn) > eps) // пока не достигнем необходимой точности, будет продолжать вычислять { x0 = xn; xn = x0-f(x0)/df(x0); // непосредственно формула Ньютона cout<<++i<<"-th iteration = "<<xn<<"\n"; } cout<<"\nRoot = "<<xn; // вывод вычисленного корня } cout<<"\nExit?=>"; cin>>exit; } while (exit!=1); // пока пользователь не ввел exit = 1 return 0; } |
Посмотрим, как это работает. Нажмем на зеленый треугольник в верхнем левом углу экрана, или же клавишу F5.
Если происходит ошибка компиляции «Ошибка error LNK1123: сбой при преобразовании в COFF: файл недопустим или поврежден», то это лечится либо установкой первого Service pack 1, либо в настройках проекта Свойства -> Компоновщик отключаем инкрементную компоновку.
Рис. 4. Решение ошибки компиляции проекта
Мы будем искать корни у функции f(x) = x2-2.
Сначала проверим работу приложения на «неправильных» входных данных. На отрезке [3; 5] нет корней, наша программа должна выдать сообщение об ошибке.
У нас появилось окно приложения:
Рис. 5. Ввод входных данных
Введем границы отрезка 3 и 5, и точность 0.05. Программа, как и надо, выдала сообщение об ошибке, что на данном отрезке корней нет.
Рис. 6. Ошибка «На этом отрезке корней нет!»
Выходить мы пока не собираемся, так что на сообщение «Exit?» вводим «0».
Теперь проверим работу приложения на корректных входных данных. Введем отрезок [0; 2] и точность 0.0001.
Рис. 7. Вычисление корня с необходимой точностью
Как мы видим, необходимая точность была достигнута уже на 4-ой итерации.
Чтобы выйти из приложения, введем «Exit?» => 1.
