Для сравнения эффективности численных методов решения нелинейных уравнений рассмотрим задачу нахождения приближенного решения уравнения (1):
, (1)
где угол x задан в градусах. Указанное уравнение можно переписать в виде (поскольку для используемой стандартной функции sin(х) угол должен задаваться в радианах):
(2)
Для графического отсечения корней достаточно построить график функции, показанный на рис. 1:
Рис. 1. График функции y=
Из рис. 1 видно, что корень уравнения лежит в промежутке x∈(6;8).
Для уточнения корней может использоваться один из следующих методов [1–2]:
Метод итерации
Метод половинного деления
Метод Ньютона
Метод хорд
Метод итерации — численный метод решения математических задач, используемый для приближённого решения алгебраических уравнений и систем. Суть метода заключается в нахождении по приближённому значению величины следующего приближения (являющегося более точным). Метод позволяет получить решение с заданной точностью в виде предела последовательности итераций. Характер сходимости и сам факт сходимости метода зависит от выбора начального приближения решения.
В программе уже введено начальное приближение , значение eps, само уравнение в функцию ничего вводить не надо. Есть вторая версия программы которая будет ниже где можно вписать свое eps и начальное приближение, для каждой из последующих программ оно будет схоже.
Кодпрограммы (C++):
#define _USE_MATH_DEFINES
#include <iostream>
#include <cmath>
using namespace std;
double find(double x, double eps)
{
double rez; int iter = 0;
cout << "Начальноеприближение x0=" << x << "";
cout << endl;
do {
rez = x;
x = 1 / (sin(M_PI*x / 180));
iter++;
}
while (fabs(rez - x) > eps && iter<20000); // Числоитерацийограничены int в c++
cout << iter << " - Число Итераций" << endl;
cout << "Ответ: ";
return x;
}
int main()
{
cout <<find(7, 0.00001); //Обращение к функции и где вводим eps
cin.get();
return 0;
}
Код программы на C++ с вводом eps:
#define _USE_MATH_DEFINES
#include <iostream>
#include <cmath>
using namespace std;
double find(double x, double eps)
{
double rez; int iter = 0;
cout << "Начальноеприближение x0=" << x << "";
cout << endl;
do {
rez = x;
x = 1 / (sin(M_PI*x / 180));
iter++;
}
while (fabs(rez - x) > eps && iter<20000); // Числоитерацийограничены int в c++
cout << iter << " - Число Итераций" << endl;
cout << "Ответ: ";
return x;
}
int main()
{
cout << “Введите значение eps” << endl;
cin << eps;
find(7, eps); //Обращение к функции и где вводим eps
cin.get();
return 0;
}
В эту и во все приведенные ниже программы исходная функция, значение eps, начальное приближение и концы промежутка вводятся сразу, а в некоторых случаях и её производная, при запуске программы вводить ничего не нужно все уже есть в ней.
Вывод программы показан на рис. 1 (он совпадает для всех 4-х методов):
Рис. 2. Вывод программы
Блок схема метода итераций:
Рис. 3. Блок схема метода итераций
Метод Ньютона, алгоритм Ньютона (также известный как метод касательных) — это итерационный численный метод нахождения корня (нуля) заданной функции. Метод был впервые предложен английским физиком, математиком и астрономом Исааком Ньютоном (1643 — 1727). Поиск решения осуществляется путём построения последовательных приближений и основан на принципах простой итерации.
КодПрограммы (C++):
#define _USE_MATH_DEFINES
#include <iostream>
#include <cmath>
using namespace std;
double find(double x, double eps)
{
double f, df; int iter = 0;
cout << "x0=" << x << " ";
cout << endl;
do {
f = sin(M_PI*x / 180) - 1 / x;
df = M_PI / 180 * cos(M_PI*x / 180) + 1 / (x*x);
x = x - f / df;
iter++;
}
while (fabs(f) > eps && iter< 20000);
cout << iter << " Итераций" << endl;
return x;
}
int main()
{
cout << find(1, 0.00001);
cin.get(); return 0;
}
Блок схемаметода Ньютона:
Рис. 4 Блок схема метода Ньютона
Метод хорд (метод также известен как Метод секущих) один из методов решения нелинейных уравнений и основан на последовательном сужении интервала, содержащего единственный корень уравнения. Итерационный процесс выполняется до того момента, пока не будет достигнута заданная точность.
Кодпрограммы (C++):
#define _USE_MATH_DEFINES
#include <iostream>
#include <cmath>
using namespace std;
double find(double x0, double x1, double eps)
{
double rez = x1, f0, f;
int iter = 0;
cout << "x0=" << x0 << " x1=" << x1 << " ";
cout << endl;
do {
f = sin(M_PI*rez / 180) - 1 / rez;
f0 = sin(M_PI*x0 / 180) - 1 / x0;
rez = rez - f / (f - f0)*(rez - x0);
iter++;
} while (fabs(f) > eps && iter< 20000);
cout << iter << " Итераций" << endl;
return rez;
}
int main()
{
cout << find(1.0, 10.0, 0.000001);
cin.get(); return 0;
}
Блок схема метода хорд:
Рис. 5 Блок схема метода хорд
Метод половинного деления (Метод дихотомии) Если x0, x1 - приближенные значения корня уравнения f(x) = 0 и выполняется условие
то последующие приближения находятся по формуле
и вычисляется f(xi). Если f(xi)=0, то корень найден. В противном случае из отрезков выбирается тот, на концах которого f(x) принимает значения разных знаков, и проделывается аналогичная операция. Процесс продолжается до получения требуемой точности.
Код программы (C++):
#define _USE_MATH_DEFINES
#include <iostream>
#include <cmath>
using namespace std;
double func(double x)
{
return (sin(M_PI*x / 180) - 1 / x);
}
double find(double x0, double x1, double eps)
{
double left = x0, right = x1, x, fl, fr, f;
int iter = 0;
cout << "x0=" << x0 << " x1=" << x1 << " ";
cout << endl;
do {
x = (left + right) / 2;
f = func(x);
if (f > 0) right = x;
else left = x;
iter++;
} while (fabs(f) > eps && iter< 20000);
cout << iter << " Итераций" << endl;
return x;
}
int main()
{
cout << find(1.0, 10.0, 0.000001);
cin.get(); return 0;
}
Блок схема метода половинного деления:
Рис. 6 Блок схема метода половинного деления
Сравним все методы по количеству итераций с разной точностью вычисления и соберем все данные в таблицу:
Таблица
Сравнение методов по числу итераций
Методы |
eps |
iter |
eps |
iter |
eps |
iter |
Итераций |
0,001 |
1212 |
0,0001 |
1605 |
0,00001 |
1998 |
Ньютона |
0,001 |
6 |
0,0001 |
7 |
0,00001 |
7 |
Хорд |
0,001 |
18 |
0,0001 |
26 |
0,00001 |
35 |
Половинного деления |
0,001 |
8 |
0,0001 |
10 |
0,00001 |
14 |
Из таблицы видно, что для нахождения приближенного решения рассматриваемого уравнения больше все итераций требует метод итераций, за ним метод хорд, половинного деления и Ньютона, также стоит отметить что метод половинного деления производительней других за счет того, что пример получился максимально подходящий для этого метода, а метод итераций менее производительный за счет того , что не была произведена дополнительная проверка на достаточное условие сходимости.
В ходе выполнения данной работы были изучены следующие методы решения: метод итерации, метод половинного деления, метод хорд и метод Ньютона , а также углублены познания по теме численные методы решения нелинейных уравнений на примере решения уравнения .
Список литературы
Численные методы / Под ред. Лапчика М.П.. - М.: Academia, 2017.
Бахвалов, Н.С. Численные методы. Решения задач и упражнения: Учебное пособие / Н.С. Бахвалов, А.А Корнев, Е.В. Чижонков. - М.: Бином 2015.
Вабищевич, П.Н. Численные методы: Вычислительный практикум / П.Н. Вабищевич. - М.: Ленанд, 2016.