Advertisement
ms_shnits

Метод Ньютона для поиска корней и производных

Dec 4th, 2018
305
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 5.54 KB | None | 0 0
  1. #include <stdlib.h>
  2. #include <iostream>
  3. #include <math.h>
  4.  
  5. // задаем константу - шаг по x (для вычисления производных)
  6. #define delta 1e-5
  7.  
  8. using namespace std;
  9.  
  10.  
  11. /*********
  12.     ВСЯКИЕ ВСПОМОГАТЕЛЬНЫЕ ТИПЫ И ПОДПРОГРАММЫ
  13. */
  14.  
  15. // описываем тип данных: вещественнозначная функция
  16. typedef double (*Func)(double x);
  17.  
  18.  
  19. // вычисление производной заданной вещественнозначной функции
  20. double Derivative (double x, Func F)
  21. {
  22.     return ((*F)(x+delta) - (*F)(x-delta)) / (2*delta);
  23. }
  24.  
  25.  
  26. // метод Ньютона для вычисления корня вещественнозначной функции
  27. double Newton (double x, double border_min, double border_max, double eps, Func F)
  28. {
  29.     while (border_min <= x && x <= border_max && fabs((*F)(x)) > eps)
  30.         x -= (*F)(x) / Derivative(x, F);
  31.     return x;
  32. }
  33.  
  34. // нахождение корня вещественнозначной функции методом Ньютона
  35. double GetRoot (double border_min, double border_max, double eps, Func F)
  36. {
  37.     double x;
  38.  
  39.     // пытаемся искать корень от левой границы заданного интервала
  40.     x = Newton(border_min, border_min, border_max, eps, F);
  41.     if (border_min <= x && x <= border_max)
  42.         return x;
  43.  
  44.     // пытаемся искать корень от правой границы заданного интервала
  45.     x = Newton(border_max, border_min, border_max, eps, F);
  46.     if (border_min <= x && x <= border_max)
  47.         return x;
  48.  
  49.     // пытаемся искать корень из центра интервала
  50.     x = Newton((border_max + border_min)/2, border_min, border_max, eps, F);
  51.     if (border_min <= x && x <= border_max)
  52.         return x;
  53.  
  54.     // если ничего не получилось, вернули х за пределами заданного интервала
  55.     return border_min - 1;
  56. }
  57.  
  58. // заготовка для интересующей нас функции
  59. double f (double x);
  60.  
  61. // "обёртка" для вычисления производной интересующей нас функции
  62. double df (double x)
  63. {
  64.     return Derivative(x, &f);
  65. }
  66.  
  67. // "обёртка" для вычисления второй производной интересующей нас функции
  68. double d2f (double x)
  69. {
  70.     return Derivative(x, &df);
  71. }
  72.  
  73.  
  74. /*********
  75.     ИНТЕРЕСУЮЩАЯ НАС ФУНКЦИЯ
  76. */
  77. double f (double x)
  78. {
  79.     return tan(7 * x) + pow(x, 2) * sin(x) + 1;
  80. }
  81. /*********/
  82.  
  83.  
  84. /*********
  85.     ТОЧКА ВХОДА
  86. */
  87. int main()
  88. {
  89.     setlocale(LC_ALL, "Rus");
  90.  
  91.     double a, b, eps;
  92.  
  93.  
  94.     // вводим начальные данные
  95.     cout << "Введите границы отрезка [a;b] для анализа функции ";
  96.     cout << "\nВведите левую границу отрезка a = "; cin >> a;
  97.     cout << "Введите правую границу отрезка b = "; cin >> b;
  98.     cout << "Введите значение погрешности eps = "; cin >> eps;
  99.     cout << "\n";
  100.  
  101.     //a = 2.9;
  102.     //b = 3.3;
  103.     //eps = 1e-5;
  104.  
  105.     // проверяем введенные данные на корректность
  106.     if (a >= b)
  107.     {
  108.         cout << "Неверно указан интервал поиска" << endl;
  109.         system("pause");
  110.         return 0;
  111.     }
  112.  
  113.     if (eps <= 0)
  114.     {
  115.         cout << "Значение погрешности должно быть положительным" << endl;
  116.         system("pause");
  117.         return 0;
  118.     }
  119.  
  120.  
  121.     double x;
  122.  
  123.  
  124.     // ищем корни функции методом Ньютона
  125.     x = GetRoot (a, b, eps, &f);
  126.  
  127.     if (a > x || x > b)
  128.         cout << "Корней методом Ньютона найти не удалось." << endl;
  129.     else
  130.         cout << "Корень функции: " << x << endl;
  131.  
  132.  
  133.     // ищем нули производной методом Ньютона
  134.     x = GetRoot (a, b, eps, &df);
  135.  
  136.     while(true)
  137.     {
  138.         // если вернулось число за пределами интервала [a, b], то корень найти не удалось
  139.         if (a > x || x > b)
  140.         {
  141.             cout << "Точек экстремума методом Ньютона найти не удалось." << endl;
  142.             break;
  143.         }
  144.  
  145.         // если вторая производная отрицательная, то найденная точка - точка максимума
  146.         if (d2f(x) < -eps)
  147.         {
  148.             cout << "Точка максимума: " << x << "\tМаксимум: " << f(x) << endl;
  149.             break;
  150.         }
  151.  
  152.         // если вторая производная положительная, то найденная точка - точка минимума
  153.         if (d2f(x) > eps)
  154.         {
  155.             cout << "Точка минимума: " << x << "\tМминимум: " << f(x) << endl;
  156.             break;
  157.         }
  158.  
  159.         // если вторая производная - в пределах погрешности, то, наверно, найденная точка - точка перегиба
  160.         cout << "Точка перегиба: " << x << "\tЗначение функции: " << f(x) << endl;
  161.         break;
  162.     }
  163.  
  164.  
  165.     system("pause");
  166.  
  167.     return 0;
  168. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement