vadimk772336

Untitled

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