vadimk772336

Untitled

Nov 17th, 2019
219
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 13.03 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) // k - кол во скобок для раскрытия (сколько надо, напр в ньютоне нужно не все), 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; // Домножаем разделенную разность на скобки (x-x[0])...(x-x[i-1])
  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.             mas_coeff_polynom[j] = (mas_coeff_polynom[j]);
  180.         }
  181.     }
  182.     for (j = 0; j < Count; j++) {
  183.         cout << mas_coeff_polynom[j] << " ";
  184.     }
  185. }
  186.  
  187. void PolynomN(Node* Array, int Count, double*& mas_coeff_polynom, double *DD_massiv)
  188. {
  189.     int j;
  190.     double dd;
  191.     double* tmp_massiv_coeff = new double[Count]; // массив А0...An конечных коэфф для одного шага цикла сколько точек, столько и коэфф
  192.     double* brackets_massiv = new double[Count - 1]; //массив X0,,,Хn
  193.  
  194.     int i;
  195.  
  196.     for (int j = 0; j < Count - 1; j++) {
  197.         mas_coeff_polynom[j] = 0.0;
  198.         brackets_massiv[j] = 0.0;
  199.     }
  200.  
  201.     mas_coeff_polynom[Count - 1] = 0.0;
  202.  
  203.     for (int j = 0; j < Count - 1; j++) { //Кладем все иксы
  204.         brackets_massiv[j] = 0.0 - Array[j].x;
  205.     }
  206.  
  207.     mas_coeff_polynom[0] = Array[0].y; // 0 индекс хранит свободный член итого многочлена
  208.  
  209.     for (i = 1; i < Count; i++) {
  210.         for (j = 0; j < Count; j++) {
  211.             tmp_massiv_coeff[j] = 0.0;
  212.         }
  213.  
  214.         dd = DD_massiv[i]; //Ищем итую РР
  215.  
  216.         get_koef_polynom(brackets_massiv, tmp_massiv_coeff, i); //Возвращает кф при перемножении (х-Х0)...(х-Хi+1)
  217.  
  218.         for (j = 0; j < Count; j++) {
  219.             tmp_massiv_coeff[j] = (tmp_massiv_coeff[j]);
  220.             mas_coeff_polynom[j] += (tmp_massiv_coeff[j] * dd);
  221.         }
  222.     }
  223.     for (j = 0; j < Count; j++) {
  224.         cout << (mas_coeff_polynom[j]) << " ";
  225.     }
  226. }
  227.  
  228. 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)
  229. { //Строит таблицу для инт-го полинома и табл погрешности между ориг и ним
  230.     int k;
  231.     double y_value, x_value;
  232.  
  233.     ofstream fout(file_name); //Лежит таблица от интерполяции (по заданным точкам) по выбранному методу для графика (точки сами выбрали)
  234.     ofstream pogr(file_name_error);
  235.  
  236.     method Func = PolynomN_dot;
  237.     if (method_name == "Lagrange")
  238.         method Func = PolynomLG_dot;
  239.  
  240.     for (k = 0; k < MyCount; k++) {
  241.         x_value = MyArray[k].x;
  242.         fout << x_value << " ";
  243.         pogr << x_value << " ";
  244.         y_value = Func(x_value, Array, Count, DD_massiv);
  245.  
  246.         fout << y_value << endl;
  247.  
  248.         pogr << abs(y_value - MyArray[k].y) << endl;
  249.     }
  250.  
  251.     fout.close();
  252. }
  253.  
  254. void orig_table_in_file(Node* Array, int Count)
  255. { // Функция берет таблицу иксов и игриков, количество точек в которых считаем знач полинома,
  256.     // По итогу имеем файл с 2 столбацами: х и у
  257.     int k;
  258.     double y_value, x_value;
  259.  
  260.     ofstream fout("D:/Original_graphic.txt");
  261.  
  262.     for (k = 0; k < Count; k++) { //n иксов подставляев в полином степени n-1
  263.         x_value = Array[k].x;
  264.         fout << x_value << " ";
  265.         y_value = Array[k].y;
  266.         fout << y_value << endl;
  267.     }
  268.  
  269.     fout.close();
  270. }
  271.  
  272. void ApproximateError(Node* Array, Node* MyArray, int MyCount, int Count) //Значение MaxDerivative получаем из питона и вручную подст
  273. { // Приближенная погрешность
  274.     double MaxDerivative;
  275.     ifstream N("D:/test1.txt");
  276.     N >> MaxDerivative;
  277.     N.close();
  278.  
  279.  
  280.     //ifstream Max("D:/Max.txt");
  281.     //Max >> MaxDerivative;
  282.     //Max.close();
  283.  
  284.     ofstream AppError("D:/AppError.txt");
  285.  
  286.     double x_value, y_value;
  287.  
  288.     for (int k = 0; k < MyCount; k++) {
  289.         x_value = MyArray[k].x;
  290.         AppError << x_value << "   ";
  291.  
  292.         y_value = abs((MaxDerivative * W(x_value, Count, Array)) / Factorial(Count + 1));
  293.  
  294.         AppError << y_value << endl;
  295.     }
  296.     AppError.close();
  297. }
  298.  
  299. void display_PolyDiff(double* mas_coeff_polynomLag, double* mas_coeff_polynomNew, int CountNodes)
  300. {
  301.     for (int i = 0; i < CountNodes; i++)
  302.         cout << mas_coeff_polynomLag[i] - mas_coeff_polynomNew[i] << " ";
  303. }
  304.  
  305. void Display_table_points(Node* Array, int count)
  306. {
  307.     for (int i = 0; i < count; i++) {
  308.         cout << Array[i].x << "  " << Array[i].y << endl;
  309.     }
  310. }
  311.  
  312. int main()
  313. {
  314.  
  315.     setlocale(LC_ALL, "RUS");
  316.     //ДАННЫЕ
  317.     Interval Interval;
  318.     int CountNodes, MyNodes = 100;
  319.     functiontype Func = &Myfunc;
  320.  
  321.     cout << "Enter the number of nodes: " << endl;
  322.     cin >> CountNodes;
  323.     CountNodes += 1;
  324.  
  325.     //Передача CountNodes В Питон
  326.     ofstream N("D:/Degree_Derivative.txt");
  327.     N << CountNodes + 1;
  328.     N.close();
  329.     system("pause");
  330.  
  331.     Interval.InitialNode = -2;
  332.     Interval.EndNode = 2;
  333.  
  334.     double* mas_coeff_polynomNew = new double[CountNodes];
  335.     double* mas_coeff_polynomLag = new double[CountNodes];
  336.  
  337.  
  338.  
  339.     //По заданным точкам(Nodes)
  340.     Node* ArrayUniformNodes = new Node[CountNodes];                                                     // Массив с равномерными узлами
  341.     ValueUniformTable(&Func, ArrayUniformNodes, Interval.InitialNode, Interval.EndNode, CountNodes);    // Заполнение таблицы равномерных значений
  342.  
  343.     //Построение графика(MyNodes)
  344.     Node* Graph_ArrayUniformNodes = new Node[MyNodes];                                                  // Массив с равномерными узлами для построение графика (MyNodes)
  345.     ValueUniformTable(&Func, Graph_ArrayUniformNodes, Interval.InitialNode, Interval.EndNode, MyNodes); //Заполнение таблицы для построение графика
  346.  
  347.     //Получаем массив РР для передачи функциям
  348.     double* DD_massiv = new double[CountNodes];
  349.     DD_massiv = DividedDifference(CountNodes, ArrayUniformNodes);
  350.  
  351.     //Чебышев
  352.     //Node* ArrayChebyshevNodes = new Node[CountNodes];                                                    // Массив с Чебышевскими узлами
  353.     //ValueChebyshevTable(&Func, ArrayChebyshevNodes, Interval.InitialNode, Interval.EndNode, CountNodes);   // Заполнение таблицы Чебышевских значений
  354.     //table_in_file(Graph_ArrayUniformNodes, ArrayChebyshevNodes, MyNodes, CountNodes, "D:/Lagrange_Cheb.txt", "D:/Pogr_Lagrange_Cheb.txt", "Lagrange", DD_massiv);
  355.     //table_in_file(Graph_ArrayUniformNodes, ArrayChebyshevNodes, MyNodes, CountNodes, "D:/Newton_Cheb.txt", "D:/Pogr_Newton_Cheb.txt", "Newton", DD_massiv);
  356.  
  357.     cout << endl;
  358.     cout << "Таблица значений по равномерной сетке" << endl;
  359.     Display_table_points(ArrayUniformNodes, CountNodes);
  360.     cout << endl;
  361.  
  362.     //Заполнение массивов mas_coeff_polynomLag, mas_coeff_polynomNew коэффициентами при соот-х степенях полиномов
  363.     cout << "Полином Лагранжа:" << endl;
  364.     PolynomLG(ArrayUniformNodes, CountNodes, mas_coeff_polynomLag);
  365.     cout << endl << endl << "Полином Ньютона:" << endl;
  366.     PolynomN(ArrayUniformNodes, CountNodes, mas_coeff_polynomNew, DD_massiv);
  367.     cout << endl << endl;
  368.  
  369.     //Вывод разности между полиномами Лагранжа и Ньютона
  370.     cout << "Разность между полиномами Лагранжа и Ньютона:" << endl;
  371.     display_PolyDiff(mas_coeff_polynomLag, mas_coeff_polynomNew, CountNodes);
  372.     cout << endl;
  373.  
  374.     //Запись точек в файл для построения
  375.         //Равномерная сетка
  376.     table_in_file(Graph_ArrayUniformNodes, ArrayUniformNodes, MyNodes, CountNodes, "D:/Lagrange.txt", "D:/Pogr_Lagrange.txt", "Lagrange", DD_massiv);
  377.     table_in_file(Graph_ArrayUniformNodes, ArrayUniformNodes, MyNodes, CountNodes, "D:/Newton.txt", "D:/Pogr_Newton.txt", "Newton", DD_massiv);
  378.     orig_table_in_file(Graph_ArrayUniformNodes, MyNodes); //Подставляет 100 точек в ориг функцию
  379.  
  380.     // Приближенная погрешность
  381.     ApproximateError(ArrayUniformNodes, Graph_ArrayUniformNodes, MyNodes, CountNodes);
  382.  
  383.     system("pause");
  384.     return 0;
  385. }
Advertisement
Add Comment
Please, Sign In to add comment