Advertisement
Guest User

Untitled

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