Advertisement
Guest User

Untitled

a guest
Nov 18th, 2019
132
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 13.52 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) + ((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.             tmp_massiv_coeff[j] = (tmp_massiv_coeff[j]);
  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 = PolynomN_dot;
  235.     if (method_name == "Lagrange")
  236.         method Func = PolynomLG_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("H:/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) //т
  271. {
  272.     double MaxDerivative = Factorial(Count + 1);
  273.     ofstream AppError("H:/AppError.txt");
  274.  
  275.     double x_value, y_value;
  276.  
  277.     for (int k = 0; k < MyCount; k++) {
  278.         x_value = MyArray[k].x;
  279.         AppError << x_value << "   ";
  280.  
  281.         y_value = abs(W(x_value, Count, Array));
  282.  
  283.         AppError << y_value << endl;
  284.     }
  285.     AppError.close();
  286. }
  287.  
  288. void display_PolyDiff(double* mas_coeff_polynomLag, double* mas_coeff_polynomNew, int CountNodes)
  289. {
  290.     for (int i = 0; i < CountNodes; i++)
  291.         cout << mas_coeff_polynomLag[i] - mas_coeff_polynomNew[i] << " ";
  292. }
  293.  
  294. void Display_table_points(Node* Array, int count)
  295. {
  296.     for (int i = 0; i < count; i++) {
  297.         cout << Array[i].x << "  " << Array[i].y << endl;
  298.     }
  299. }
  300.  
  301. int main()
  302. {
  303.  
  304.     setlocale(LC_ALL, "RUS");
  305.     //ДАННЫЕ
  306.     Interval Interval;
  307.     int CountNodes, MyNodes = 100;
  308.     functiontype Func = &Myfunc;
  309.  
  310.     cout << "Enter the n: " << endl;
  311.     cin >> CountNodes;
  312.     CountNodes += 1;
  313.     cout << "Number of Nodes is " << CountNodes << endl << endl;
  314.  
  315.     Interval.InitialNode = -2;
  316.     Interval.EndNode = 2;
  317.  
  318.     double* mas_coeff_polynomNew = new double[CountNodes];
  319.     double* mas_coeff_polynomLag = new double[CountNodes];
  320.  
  321.  
  322.  
  323.     //По заданным точкам(Nodes)
  324.     Node* ArrayUniformNodes = new Node[CountNodes];                                                     // Массив с равномерными узлами
  325.     ValueUniformTable(&Func, ArrayUniformNodes, Interval.InitialNode, Interval.EndNode, CountNodes);    // Заполнение таблицы равномерных значений
  326.  
  327.     //Построение графика(MyNodes)
  328.     Node* Graph_ArrayUniformNodes = new Node[MyNodes];                                                  // Массив с равномерными узлами для построение графика (MyNodes)
  329.     ValueUniformTable(&Func, Graph_ArrayUniformNodes, Interval.InitialNode, Interval.EndNode, MyNodes); //Заполнение таблицы для построение графика
  330.  
  331.     //Получаем массив РР для передачи функциям
  332.     double* DD_massiv = new double[CountNodes];
  333.     DD_massiv = DividedDifference(CountNodes, ArrayUniformNodes);
  334.  
  335.     //Чебышёв
  336.     Node* ArrayChebyshevNodes = new Node[CountNodes];                                                    // Массив с Чебышёвскими узлами
  337.     ValueChebyshevTable(&Func, ArrayChebyshevNodes, Interval.InitialNode, Interval.EndNode, CountNodes);   // Заполнение таблицы Чебышёвских значений
  338.    
  339.     /*Node* Graph_ArrayChebyshevNodes = new Node[MyNodes];                                                  // Массив с равномерными узлами для построение графика (MyNodes)
  340.     ValueUniformTable(&Func, Graph_ArrayChebyshevNodes, Interval.InitialNode, Interval.EndNode, MyNodes); //Заполнение таблицы для построение графика
  341.     table_in_file(Graph_ArrayChebyshevNodes, ArrayChebyshevNodes, MyNodes, CountNodes, "H:/Lagrange_Cheb.txt", "H:/Pogr_Lagrange_Cheb.txt", "Lagrange", DD_massiv);
  342.     table_in_file(Graph_ArrayChebyshevNodes, ArrayChebyshevNodes, MyNodes, CountNodes, "H:/Newton_Cheb.txt", "H:/Pogr_Newton_Cheb.txt", "Newton", DD_massiv);*/
  343.    
  344.     /*
  345.     cout << "Таблица значений по Чебышёвской сетке" << endl;
  346.     Display_table_points(ArrayUniformNodes, CountNodes);
  347.     cout << endl;
  348.  
  349.     cout << "Полином Лагранжа Чебышёв:" << endl;
  350.     PolynomLG(ArrayChebyshevNodes, CountNodes, mas_coeff_polynomLag);
  351.     cout << endl << endl << "Полином Ньютона Чебышёв:" << endl;
  352.     PolynomN(ArrayChebyshevNodes, CountNodes, mas_coeff_polynomNew, DD_massiv);
  353.     cout << endl << endl;
  354.  
  355.     //Вывод разности между полиномами Лагранжа и Ньютона
  356.     cout << "Разность между полиномами Лагранжа и Ньютона по Чебышёву:" << endl;
  357.     display_PolyDiff(mas_coeff_polynomLag, mas_coeff_polynomNew, CountNodes);
  358.     cout << endl;
  359.     */
  360.     /*****************Конец**************/
  361.  
  362.     cout << endl;
  363.     cout << "Таблица значений по равномерной сетке" << endl;
  364.     Display_table_points(ArrayUniformNodes, CountNodes);
  365.     cout << endl;
  366.  
  367.  
  368.    
  369.  
  370.     //Заполнение массивов mas_coeff_polynomLag, mas_coeff_polynomNew коэффициентами при соот-х степенях полиномов
  371.     cout << "Полином Лагранжа:" << endl;
  372.     PolynomLG(ArrayUniformNodes, CountNodes, mas_coeff_polynomLag);
  373.     cout << endl << endl << "Полином Ньютона:" << endl;
  374.     PolynomN(ArrayUniformNodes, CountNodes, mas_coeff_polynomNew, DD_massiv);
  375.     cout << endl << endl;
  376.  
  377.     //Вывод разности между полиномами Лагранжа и Ньютона
  378.     cout << "Разность между полиномами Лагранжа и Ньютона:" << endl;
  379.     display_PolyDiff(mas_coeff_polynomLag, mas_coeff_polynomNew, CountNodes);
  380.     cout << endl;
  381.  
  382.     //Запись точек в файл для построения
  383.     //Равномерная сетка
  384.     table_in_file(Graph_ArrayUniformNodes, ArrayUniformNodes, MyNodes, CountNodes, "H:/Lagrange.txt", "H:/Pogr_Lagrange.txt", "Lagrange", DD_massiv);
  385.     table_in_file(Graph_ArrayUniformNodes, ArrayUniformNodes, MyNodes, CountNodes, "H:/Newton.txt", "H:/Pogr_Newton.txt", "Newton", DD_massiv);
  386.     orig_table_in_file(Graph_ArrayUniformNodes, MyNodes); //Подставляет 100 точек в ориг функцию
  387.  
  388.     // Приближенная погрешность
  389.     ApproximateError(ArrayUniformNodes, Graph_ArrayUniformNodes, MyNodes, CountNodes);
  390.  
  391.     system("pause");
  392.     return 0;
  393. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement