vadimk772336

Untitled

Nov 18th, 2019
218
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 12.61 KB | None | 0 0
  1. #include <iostream>
  2. #include <math.h>
  3. #include <vector>
  4. #include <Windows.h>
  5. #include <stdlib.h>
  6. #include <fstream>
  7. #include <string.h>
  8. using namespace std;
  9. const double PI = 3.1415926535897932384626433832795;
  10. typedef double(*functiontype)(double x);
  11.  
  12. typedef struct Node {
  13.     double x, y;
  14. } Node;
  15.  
  16. typedef double(*method)(double x, Node* Array, int Count, double *DD_massiv);
  17.  
  18. typedef struct Interval {
  19.     double InitialNode, EndNode;
  20. } Interval;
  21.  
  22. int Factorial(int n)
  23. { // Факториал
  24.     int x = 1;
  25.     for (int i = 1; i <= n; i++) {
  26.         x *= i;
  27.     }
  28.     return x;
  29. }
  30.  
  31. //Возвращает число, возведенное в cтепень i
  32. double get_degree(double x, int degree)
  33. {
  34.     int i;
  35.     double y = x;
  36.     if (degree == 0)
  37.         return 1;
  38.  
  39.     for (i = 0; i < degree - 1; i++)
  40.         y *= x;
  41.     return y;
  42. }
  43.  
  44. double Myfunc(double x)
  45. {
  46.     return ( x / (x*x+1));
  47. }
  48.  
  49. void ValueUniformTable(functiontype* f, Node* Array, double Initial, double End, int Count) // Передаем массив в который все будет записано
  50. { // Создание равномерной таблицы значений
  51.     double step = abs(Initial - End) / (Count - 1);
  52.     Array[0].x = Initial;
  53.     Array[0].y = (*f)(Array[0].x);
  54.     for (int i = 1; i < Count; i++) {
  55.         Array[i].x = Array[i - 1].x + step;
  56.         Array[i].y = (*f)(Array[i].x);
  57.     }
  58. }
  59.  
  60. void ValueChebyshevTable(functiontype* f, Node* Array, double Initial, double End, int Count)
  61. { // Создание таблицы Чебышевских значений
  62.     for (int i = 0; i < Count; i++) {
  63.         Array[i].x = ((End + Initial) / 2)
  64.             + ((End - Initial) / 2) * cos(((2 * i + 1) * PI) / (2 * (Count + 1)));
  65.         Array[i].y = (*f)(Array[i].x);
  66.     }
  67. }
  68.  
  69. double* DividedDifference(int Count, Node* Array) {
  70.     double* tmp_mas = new double[Count];
  71.     double* dd = new double[Count];
  72.     for (int i = 0; i < Count; i++) {
  73.         tmp_mas[i] = Array[i].y;
  74.         dd[i] = 0.0;
  75.     }
  76.     dd[0] = Array[0].y;
  77.     for (int i = 1; i < Count; i++) {
  78.         for (int j = 0; j < Count - i; j++) {
  79.             tmp_mas[j] = (tmp_mas[j + 1] - tmp_mas[j]) / (Array[i + j].x - Array[j].x);
  80.         }
  81.         dd[i] = tmp_mas[0];
  82.     }
  83.     return dd;
  84. }
  85.  
  86. double W(double x, int n, Node* Array)
  87. { // Полином вида: (x - x1) * (x - x2) * ... * (x - xn)
  88.     double w = 1;
  89.     for (int i = 0; i < n; i++) {
  90.         w *= (x - Array[i].x);
  91.     }
  92.     return w;
  93. }
  94.  
  95. void get_koef_polynom(double* mas, double* res, int CountBrackets)
  96. {
  97.     int i;
  98.     double* anx = new double[CountBrackets + 1];
  99.     double* ann = new double[CountBrackets + 1];
  100.     res[0] = (mas[0]);
  101.     res[1] = 1;
  102.     int j;
  103.     for (j = 0; j <= CountBrackets; j++) {
  104.         anx[j] = 0.0;
  105.         ann[j] = 0.0;
  106.     }
  107.  
  108.  
  109.     for (i = 1; i < CountBrackets; i++)
  110.         for (j = 0; j <= i + 1; j++)
  111.         {
  112.             anx[j + 1] = res[j];
  113.             ann[j] = (res[j] * (mas[i]));
  114.             res[j] = (anx[j] + ann[j]);
  115.         }
  116. }
  117.  
  118. // Полином Лагранжа в точке
  119. double PolynomLG_dot(double x, Node* Array, int Count, double *DD_massiv)
  120. {
  121.     double Polynom = 0;
  122.     for (int i = 0; i < Count; i++) {
  123.         double Li = 1;
  124.         for (int j = 0; j < Count; j++) {
  125.             if (i != j)
  126.                 Li *= (x - Array[j].x) / (Array[i].x - Array[j].x);
  127.         }
  128.         Polynom += Array[i].y * Li;
  129.     }
  130.     return Polynom;
  131. }
  132.  
  133. //Полином Ньютона в точке
  134. double PolynomN_dot(double x, Node* Array, int Count, double *DD_massiv)
  135. {
  136.     double Result = Array[0].y, dd;
  137.     for (int i = 1; i < Count; i++) {
  138.         dd = 0.0;
  139.         dd = DD_massiv[i];
  140.         for (int k = 0; k < i; k++)
  141.             dd = dd * (x - Array[k].x);
  142.         Result += dd;
  143.     }
  144.  
  145.     return Result;
  146. }
  147.  
  148. void PolynomLG(Node* Array, int Count, double*& mas_coeff_polynom) //Заполняет массив коэффициентами интерполяционного полинома
  149. {
  150.     int i, j, p, c;
  151.     double* tmp_massiv_coeff = new double[Count]; // Хранит коэффиценты Li
  152.     double* brackets_massiv = new double[Count - 1]; //Для раскрытия (x-x0)...(x-xn), умноженных на коэффициент
  153.  
  154.     double denominator;
  155.  
  156.     for (j = 0; j < Count; j++) {
  157.         mas_coeff_polynom[j] = 0.0;
  158.     }
  159.  
  160.     for (i = 0; i < Count; i++) {
  161.         c = 0; //Счетчик для числителя, т.к. иначе при счете по P будет дырка в массиве и get_koef_polynom не сможет посчитать (т.е. с делает сдвиг на  1 ячейку)
  162.         for (j = 0; j < Count - 1; j++) {
  163.             brackets_massiv[j] = 0.0;
  164.             tmp_massiv_coeff[j] = 0.0;
  165.         }
  166.         tmp_massiv_coeff[Count - 1] = 0.0;
  167.         denominator = Array[i].y;
  168.         for (p = 0; p < Count; p++) {
  169.             if (p != i) {
  170.                 denominator *= 1.0 / (Array[i].x - Array[p].x);
  171.                 brackets_massiv[c] = 0.0 - Array[p].x;
  172.                 c++;
  173.             }
  174.         }
  175.  
  176.         get_koef_polynom(brackets_massiv, tmp_massiv_coeff, Count - 1); //Раскрываем все скобки из возможных (по Лагранжу так) , -1 т.к. без i-ой
  177.         for (j = 0; j < Count; j++) {
  178.             mas_coeff_polynom[j] += (tmp_massiv_coeff[j] * denominator);
  179.         }
  180.     }
  181.     for (j = 0; j < Count; j++) {
  182.         cout << mas_coeff_polynom[j] << " ";
  183.     }
  184. }
  185.  
  186. void PolynomN(Node* Array, int Count, double*& mas_coeff_polynom, double *DD_massiv)
  187. {
  188.     int j;
  189.     double dd;
  190.     double* tmp_massiv_coeff = new double[Count]; // массив А0...An конечных коэфф для одного шага цикла сколько точек, столько и коэфф
  191.     double* brackets_massiv = new double[Count - 1]; //массив X0,,,Хn
  192.  
  193.     int i;
  194.  
  195.     for (int j = 0; j < Count - 1; j++) {
  196.         mas_coeff_polynom[j] = 0.0;
  197.         brackets_massiv[j] = 0.0;
  198.     }
  199.  
  200.     mas_coeff_polynom[Count - 1] = 0.0;
  201.  
  202.     for (int j = 0; j < Count - 1; j++) { //Кладем все иксы
  203.         brackets_massiv[j] = 0.0 - Array[j].x;
  204.     }
  205.  
  206.     mas_coeff_polynom[0] = Array[0].y; // 0 индекс хранит свободный член итого многочлена
  207.  
  208.     for (i = 1; i < Count; i++) {
  209.         for (j = 0; j < Count; j++) {
  210.             tmp_massiv_coeff[j] = 0.0;
  211.         }
  212.  
  213.         dd = DD_massiv[i]; //Ищем итую РР
  214.  
  215.         get_koef_polynom(brackets_massiv, tmp_massiv_coeff, i); //Возвращает кф при перемножении (х-Х0)...(х-Хi+1)
  216.  
  217.         for (j = 0; j < Count; j++) {
  218.             tmp_massiv_coeff[j] = (tmp_massiv_coeff[j]);
  219.             mas_coeff_polynom[j] += (tmp_massiv_coeff[j] * dd);
  220.         }
  221.     }
  222.     for (j = 0; j < Count; j++) {
  223.         cout << (mas_coeff_polynom[j]) << " ";
  224.     }
  225. }
  226.  
  227. void table_in_file(Node* MyArray, Node* Array, int MyCount, int Count, string file_name, string file_name_error, string method_name, double *DD_massiv)
  228. { //Строит таблицу для инт-го полинома и табл погрешности между ориг и ним
  229.     int k;
  230.     double y_value, x_value;
  231.  
  232.     ofstream fout(file_name); //Лежит таблица от интерполяции (по заданным точкам) по выбранному методу для графика (точки сами выбрали)
  233.     ofstream pogr(file_name_error);
  234.  
  235.     method Func = PolynomN_dot;
  236.     if (method_name == "Lagrange")
  237.         method Func = PolynomLG_dot;
  238.  
  239.     for (k = 0; k < MyCount; k++) {
  240.         x_value = MyArray[k].x;
  241.         fout << x_value << " ";
  242.         pogr << x_value << " ";
  243.         y_value = Func(x_value, Array, Count, DD_massiv);
  244.  
  245.         fout << y_value << endl;
  246.  
  247.         pogr << abs(y_value - MyArray[k].y) << endl;
  248.     }
  249.  
  250.     fout.close();
  251. }
  252.  
  253. void orig_table_in_file(Node* Array, int Count)
  254. { // Функция берет таблицу иксов и игриков, количество точек в которых считаем знач полинома,
  255.     // По итогу имеем файл с 2 столбацами: х и у
  256.     int k;
  257.     double y_value, x_value;
  258.  
  259.     ofstream fout("D:/Original_graphic.txt");
  260.  
  261.     for (k = 0; k < Count; k++) { //n иксов подставляев в полином степени n-1
  262.         x_value = Array[k].x;
  263.         fout << x_value << " ";
  264.         y_value = Array[k].y;
  265.         fout << y_value << endl;
  266.     }
  267.  
  268.     fout.close();
  269. }
  270.  
  271. void ApproximateError(Node* Array, Node* MyArray, int MyCount, int Count) //т
  272. {
  273.     double MaxDerivative = Factorial(Count + 1);
  274.     ofstream AppError("D:/AppError.txt");
  275.  
  276.     double x_value, y_value;
  277.  
  278.     for (int k = 0; k < MyCount; k++) {
  279.         x_value = MyArray[k].x;
  280.         AppError << x_value << "   ";
  281.  
  282.         y_value = abs(W(x_value, Count, Array));
  283.  
  284.         AppError << y_value << endl;
  285.     }
  286.     AppError.close();
  287. }
  288.  
  289. void display_PolyDiff(double* mas_coeff_polynomLag, double* mas_coeff_polynomNew, int CountNodes)
  290. {
  291.     for (int i = 0; i < CountNodes; i++)
  292.         cout << mas_coeff_polynomLag[i] - mas_coeff_polynomNew[i] << " ";
  293. }
  294.  
  295. void Display_table_points(Node* Array, int count)
  296. {
  297.     for (int i = 0; i < count; i++) {
  298.         cout << Array[i].x << "  " << Array[i].y << endl;
  299.     }
  300. }
  301.  
  302. int main()
  303. {
  304.  
  305.     setlocale(LC_ALL, "RUS");
  306.     //ДАННЫЕ
  307.     Interval Interval;
  308.     int CountNodes, MyNodes = 100;
  309.     functiontype Func = &Myfunc;
  310.  
  311.     cout << "Enter the n: " << endl;
  312.     cin >> CountNodes;
  313.     CountNodes += 1;
  314.     cout << "Number of Nodes is " << CountNodes << endl << endl;
  315.  
  316.     Interval.InitialNode = -2;
  317.     Interval.EndNode = 2;
  318.  
  319.     double* mas_coeff_polynomNew = new double[CountNodes];
  320.     double* mas_coeff_polynomLag = new double[CountNodes];
  321.  
  322.  
  323.  
  324.     //По заданным точкам(Nodes)
  325.     Node* ArrayUniformNodes = new Node[CountNodes];                                                     // Массив с равномерными узлами
  326.     ValueUniformTable(&Func, ArrayUniformNodes, Interval.InitialNode, Interval.EndNode, CountNodes);    // Заполнение таблицы равномерных значений
  327.  
  328.     //Построение графика(MyNodes)
  329.     Node* Graph_ArrayUniformNodes = new Node[MyNodes];                                                  // Массив с равномерными узлами для построение графика (MyNodes)
  330.     ValueUniformTable(&Func, Graph_ArrayUniformNodes, Interval.InitialNode, Interval.EndNode, MyNodes); //Заполнение таблицы для построение графика
  331.  
  332.     //Получаем массив РР для передачи функциям
  333.     double* DD_massiv = new double[CountNodes];
  334.     DD_massiv = DividedDifference(CountNodes, ArrayUniformNodes);
  335.  
  336.     //Чебышев
  337.     Node* ArrayChebyshevNodes = new Node[CountNodes];                                                    // Массив с Чебышевскими узлами
  338.     ValueChebyshevTable(&Func, ArrayChebyshevNodes, Interval.InitialNode, Interval.EndNode, CountNodes);   // Заполнение таблицы Чебышевских значений
  339.     //table_in_file(Graph_ArrayUniformNodes, ArrayChebyshevNodes, MyNodes, CountNodes, "D:/Lagrange_Cheb.txt", "D:/Pogr_Lagrange_Cheb.txt", "Lagrange", DD_massiv);
  340.     //table_in_file(Graph_ArrayUniformNodes, ArrayChebyshevNodes, MyNodes, CountNodes, "D:/Newton_Cheb.txt", "D:/Pogr_Newton_Cheb.txt", "Newton", DD_massiv);
  341.     /*cout << "Полином Лагранжа Чебышев:" << endl;
  342.     PolynomLG(ArrayChebyshevNodes, CountNodes, mas_coeff_polynomLag);
  343.     cout << endl << endl << "Полином Ньютона Чебышев:" << endl;
  344.     PolynomN(ArrayChebyshevNodes, CountNodes, mas_coeff_polynomNew, DD_massiv);
  345.     cout << endl << endl;*/
  346.  
  347.     cout << endl;
  348.     cout << "Таблица значений по равномерной сетке" << endl;
  349.     Display_table_points(ArrayUniformNodes, CountNodes);
  350.     cout << endl;
  351.  
  352.     //Заполнение массивов mas_coeff_polynomLag, mas_coeff_polynomNew коэффициентами при соот-х степенях полиномов
  353.     cout << "Полином Лагранжа:" << endl;
  354.     PolynomLG(ArrayUniformNodes, CountNodes, mas_coeff_polynomLag);
  355.     cout << endl << endl << "Полином Ньютона:" << endl;
  356.     PolynomN(ArrayUniformNodes, CountNodes, mas_coeff_polynomNew, DD_massiv);
  357.     cout << endl << endl;
  358.  
  359.     //Вывод разности между полиномами Лагранжа и Ньютона
  360.     cout << "Разность между полиномами Лагранжа и Ньютона:" << endl;
  361.     display_PolyDiff(mas_coeff_polynomLag, mas_coeff_polynomNew, CountNodes);
  362.     cout << endl;
  363.  
  364.     //Запись точек в файл для построения
  365.         //Равномерная сетка
  366.     table_in_file(Graph_ArrayUniformNodes, ArrayUniformNodes, MyNodes, CountNodes, "D:/Lagrange.txt", "D:/Pogr_Lagrange.txt", "Lagrange", DD_massiv);
  367.     table_in_file(Graph_ArrayUniformNodes, ArrayUniformNodes, MyNodes, CountNodes, "D:/Newton.txt", "D:/Pogr_Newton.txt", "Newton", DD_massiv);
  368.     orig_table_in_file(Graph_ArrayUniformNodes, MyNodes); //Подставляет 100 точек в ориг функцию
  369.  
  370.     // Приближенная погрешность
  371.     ApproximateError(ArrayUniformNodes, Graph_ArrayUniformNodes, MyNodes, CountNodes);
  372.  
  373.     system("pause");
  374.     return 0;
  375. }
Advertisement
Add Comment
Please, Sign In to add comment