Advertisement
Guest User

Untitled

a guest
Apr 1st, 2020
101
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 11.57 KB | None | 0 0
  1. /*
  2. plot "D:\spline_graphic.txt" with lines title "Сплайн", "D:\original_graphic.txt" with lines title "График функции"
  3. plot "D:\difference_graphic.txt" with lines title "Разница"
  4. */
  5. #include <iostream>
  6. #include <math.h>
  7. #include <cmath>
  8. #include <Windows.h>
  9. #include <stdlib.h>
  10. #include <fstream>
  11. using namespace std;
  12. const double PI = 3.141592653589793238463;
  13.  
  14. //Для хранения сетки
  15. typedef struct Node
  16. {
  17.     double x, y;
  18. }
  19. Node;
  20.  
  21. //Задание функции
  22. typedef double(*functiontype)(double x);
  23. double Myfunc(double x)
  24. {
  25.     //return x*x*x;
  26.  
  27.     return sin(x) * sin(x);
  28.  
  29.  
  30. }
  31. functiontype Func = &Myfunc;
  32.  
  33. //Возведение числа в натуральную степень
  34. double degree(double x, int n)
  35. {
  36.     double b = x;
  37.     for (int i = 1; i < n; i++)
  38.         x *= b;
  39.     return x;
  40. }
  41.  
  42.  
  43. //Возвращает значение сплайна в точке на итервале[xi,x_i+1]
  44. double Spline(double x, double* Array_steps, double* x_massiv, Node* Array, int CountSegments)
  45. {
  46.     double h2, g1, g2, x1, x2, y1, y2;
  47.     int i = 0, k = 0;
  48.  
  49.     while ((i < CountSegments) & (k == 0)) {
  50.         if ((x <= Array[i + 1].x) & (x >= Array[i].x)) {
  51.             k = 1;
  52.             i--;
  53.         }
  54.         i++;
  55.     }
  56.  
  57.  
  58.     h2 = Array_steps[i + 1];
  59.     g1 = x_massiv[i];
  60.     g2 = x_massiv[i + 1];
  61.     x1 = Array[i].x;
  62.     x2 = Array[i + 1].x;
  63.     y1 = Array[i].y;
  64.     y2 = Array[i + 1].y;
  65.  
  66.     return (
  67.         (y1 * (x2 - x) + y2 * (x - x1)) / h2 +
  68.         ((g1 * (degree((x2 - x), 3) - h2 * h2 * (x2 - x))) + (g2 * (degree((x - x1), 3) - h2 * h2 * (x - x1)))) / (6 * h2)
  69.         );
  70. }
  71.  
  72. //Приблизительное значение 2 производной cплайна
  73. double approximate_derivative_2(double x, double* Selected_steps, double* x_massiv, Node* SelectedNode, int CountSegments)
  74. {
  75.     double delta = 1e-5;
  76.     return ((Spline(x-2*delta, Selected_steps, x_massiv, SelectedNode, CountSegments) - 2 * Spline(x - delta, Selected_steps, x_massiv, SelectedNode, CountSegments)
  77.         + Spline(x, Selected_steps, x_massiv, SelectedNode, CountSegments)) / (delta * delta));
  78. }
  79.  
  80. //Приблизительное значение 1 производной
  81. double approximate_derivative_1(double x, double* Selected_steps, double* x_massiv, Node* SelectedNode, int CountSegments)
  82. {
  83.     double delta = 1e-5;
  84.     return (Spline(x+ delta, Selected_steps, x_massiv, SelectedNode, CountSegments) - Spline(x, Selected_steps, x_massiv, SelectedNode, CountSegments)) / delta;
  85. }
  86.  
  87. //Равномерная сетка
  88. void ValueUniformTable(functiontype* f, Node* Array, double Initial, double End, int CountSegments, double* Array_steps_uni)
  89. {
  90.     double h;
  91.     ofstream fout4("D:\setka_uni.txt");
  92.     Array[0].x = -1;
  93.     Array[0].y = 0;
  94.     Array[1].x = 0;
  95.     Array[1].y = 2;
  96.     Array[2].x = 1;
  97.     Array[2].y = 4;
  98.     Array[3].x = 2;
  99.     Array[3].y = 18;
  100.     fout4 << Array[0].x << " " << Array[0].y << endl;
  101.     Array_steps_uni[0] = 0;
  102.     //  h = abs(End - Initial) / CountSegments;
  103.  
  104.     for (int i = 1; i <= 3; i++)
  105.     {
  106.  
  107.         fout4 << Array[i].x << " " << Array[i].y << endl;
  108.         Array_steps_uni[i] = Array[i].x - Array[i - 1].x;
  109.     }
  110.     fout4.close();
  111. }
  112.  
  113. //Чебышёвская сетка
  114. void ValueChebyshevTable(functiontype* f, Node* Array, double Initial, double End, int CountSegments, double* Array_steps_cheb)
  115. {
  116.     ofstream fout5("D:\setka_cheb.txt");
  117.     Array_steps_cheb[0] = 0;
  118.     Array[0].x = Initial;
  119.     Array[0].y = (*f)(Array[0].x);
  120.     fout5 << Array[0].x << " " << Array[0].y << endl;
  121.     double k1, k2, denom;
  122.     k1 = (End + Initial) / 2;
  123.     k2 = (End - Initial) / 2;
  124.     denom = 2 * (CountSegments + 1);
  125.     for (int i = 1; i < CountSegments; i++)
  126.     {
  127.         Array[CountSegments - i].x = k1 + k2 * cos(((2 * i + 1) * PI) / (denom));
  128.         Array[CountSegments - i].y = (*f)(Array[CountSegments - i].x);
  129.         fout5 << Array[CountSegments - i].x << " " << Array[CountSegments - i].y << endl;
  130.     }
  131.  
  132.     Array[CountSegments].x = End;
  133.     Array[CountSegments].y = (*f)(Array[CountSegments].x);
  134.     Array_steps_cheb[CountSegments] = Array[CountSegments].x - Array[CountSegments - 1].x;
  135.     fout5 << Array[CountSegments].x << " " << Array[CountSegments].y << endl;
  136.     fout5.close();
  137.  
  138.     for (int i = 1; i < CountSegments; i++)
  139.         Array_steps_cheb[i] = Array[i].x - Array[i - 1].x;
  140. }
  141.  
  142. //Составляет СЛАУ с учётом нач. данных и заполняет этим массив matrix_coeffs - массив вида[[a1,b1,c1,d1], [a2,b2,c2,d2],..., [an,bn,cn,dn]]
  143. void get_matrix_coeffs(functiontype* f, double** matrix_coeffs, double* Array_steps, Node* Array, double Initial, double End, int CountSegments)
  144. {
  145.     int i;
  146.     double h1, h2, A, B, y1, y2;
  147.     int matrix_size = CountSegments + 1;
  148.  
  149.     //A = approximate_derivative_2(&Func, Array[0].x);
  150.     //B = approximate_derivative_1(&Func, Array[CountSegments].x);
  151.     A = 6;
  152.     B = 24;
  153.  
  154.     //первое уравнение
  155.     h2 = Array_steps[1];
  156.     y1 = Array[0].y;
  157.     y2 = Array[1].y;
  158.     matrix_coeffs[0][0] = 0;
  159.     matrix_coeffs[0][1] = 2;
  160.     matrix_coeffs[0][2] = 1;
  161.     matrix_coeffs[0][3] = 6 * (y2 - y1 - A * h2) / (h2 * h2);
  162.  
  163.     for (i = 1; i < matrix_size - 1; i++)
  164.     {
  165.         h1 = Array_steps[i];
  166.         h2 = Array_steps[i + 1];
  167.         matrix_coeffs[i][0] = h1;
  168.         matrix_coeffs[i][1] = 2 * (h1 + h2);
  169.         matrix_coeffs[i][2] = h2;
  170.         matrix_coeffs[i][3] = 6 * ((Array[i + 1].y - Array[i].y) / h2 - (Array[i].y - Array[i - 1].y) / h1);
  171.     }
  172.  
  173.     //n+1 уравнение
  174.     h2 = Array_steps[matrix_size - 1];
  175.     y1 = Array[matrix_size - 2].y;
  176.     y2 = Array[matrix_size - 1].y;
  177.     matrix_coeffs[matrix_size - 1][0] = 0;
  178.     matrix_coeffs[matrix_size - 1][1] = 1;
  179.     matrix_coeffs[matrix_size - 1][2] = 0;
  180.     matrix_coeffs[matrix_size - 1][3] = B;
  181. }
  182.  
  183. /*Принимает на вход коэффициенты СЛАУ в виде массива matrix_coeffs - массив вида[[a1,b1,c1,d1], [a2,b2,c2,d2],..., [an,bn,cn,dn]].
  184.    Заполняет Двумерный массив прогоночных коэффициентов coeffs_massiv (0 - Кси, 1 - Эта). Находит решение в виде массива x_massiv*/
  185. void tridiagonal_matrix_algorithm(double** matrix_coeffs, double* Array_steps, Node* Array, double* x_massiv, int CountSegments)
  186. {
  187.     int i;
  188.     double denominator;
  189.     double K, E, K_prev, E_prev;
  190.     int matrix_size = CountSegments + 1;
  191.  
  192.     double** coeffs_massiv;
  193.     coeffs_massiv = new double* [matrix_size];
  194.     for (i = 0; i < matrix_size; i++)
  195.         coeffs_massiv[i] = new double[2];
  196.  
  197.     //Прямой ход
  198.     coeffs_massiv[0][0] = -(matrix_coeffs[0][2]) / matrix_coeffs[0][1];
  199.     coeffs_massiv[0][1] = (matrix_coeffs[0][3]) / matrix_coeffs[0][1];
  200.     K_prev = coeffs_massiv[0][0];
  201.     E_prev = coeffs_massiv[0][1];
  202.  
  203.     for (i = 1; i <= matrix_size - 1; i++)
  204.     {
  205.         denominator = matrix_coeffs[i][0] * K_prev + matrix_coeffs[i][1];
  206.         K = -(matrix_coeffs[i][2]) / denominator;
  207.         E = (matrix_coeffs[i][3] - matrix_coeffs[i][0] * E_prev) / denominator;
  208.         K_prev = K;
  209.         E_prev = E;
  210.         coeffs_massiv[i][0] = K;
  211.         coeffs_massiv[i][1] = E;
  212.     }
  213.  
  214.     //Обратный ход
  215.     x_massiv[matrix_size - 1] = coeffs_massiv[matrix_size - 1][1];
  216.     for (i = matrix_size - 2; i >= 0; i--)
  217.     {
  218.         x_massiv[i] = coeffs_massiv[i][0] * x_massiv[i + 1] + coeffs_massiv[i][1];
  219.     }
  220. }
  221.  
  222. //Запись в 3 файла: значений сплайна, интерполируемой функции и их разницы в countdots точках
  223. void tables_in_file(functiontype* f, Node* Array, int Count_dots, int CountSegments, double Initial, double End, double* Array_steps, double* x_massiv)
  224. {
  225.     int i = 0;
  226.     double step = (End - Initial) / (Count_dots - 1), y_value1, y_value2, x_value;
  227.  
  228.     ofstream fout1("D:/spline_graphic.txt");
  229.     ofstream fout2("D:/original_graphic.txt");
  230.     ofstream fout3("D:/difference_graphic.txt");
  231.     x_value = Initial;
  232.     for (i = 0; i < CountSegments; i++)
  233.     {
  234.         while (x_value < Array[i + 1].x)
  235.         {
  236.             fout1 << x_value << " ";
  237.             fout2 << x_value << " ";
  238.             fout3 << x_value << " ";
  239.             y_value1 = Spline(x_value, Array_steps, x_massiv, Array, CountSegments);
  240.             y_value2 = (*f)(x_value);
  241.             fout1 << y_value1 << endl;
  242.             fout2 << y_value2 << endl;
  243.             fout3 << abs(y_value2 - y_value1) << endl;
  244.             x_value += step;
  245.         }
  246.     }
  247.     fout1 << End << " ";
  248.     fout2 << End << " ";
  249.     fout1 << Spline(End, Array_steps, x_massiv, Array, CountSegments) << endl;
  250.     fout2 << (*f)(End) << endl;
  251.     fout1.close();
  252.     fout2.close();
  253.     //cout << endl << "Запись в файл осуществлена!" << endl;
  254. }
  255.  
  256. int main()
  257. {
  258.     setlocale(LC_ALL, "RUS");
  259.     functiontype Func = &Myfunc;
  260.     int CountSegments = 3, i, Countdots = 250;
  261.  
  262.     /*---------------------------------Входные данные-------------------------------------*/
  263.     double Initial = -1, End = 2;
  264.  
  265.  
  266.     /*---------------------------------Сетки-------------------------------------*/
  267.     double* Array_steps_cheb = new double[CountSegments + 1];
  268.     double* Array_steps_uni = new double[CountSegments + 1];
  269.     double* Selected_steps = new double[CountSegments + 1];
  270.  
  271.     //Равномерная сетка
  272.     Node* ArrayUniformNodes = new Node[CountSegments + 1];
  273.     ValueUniformTable(&Func, ArrayUniformNodes, Initial, End, CountSegments, Array_steps_uni);
  274.     //Чебышёв
  275.     Node* ArrayChebyshevNodes = new Node[CountSegments + 1];
  276.     ValueChebyshevTable(&Func, ArrayChebyshevNodes, Initial, End, CountSegments, Array_steps_cheb);
  277.  
  278.     Node* SelectedNode = new Node[CountSegments + 1];
  279.  
  280.     //Array_steps_cheb  ArrayChebyshevNodes  ArrayUniformNodes  Array_steps_uni
  281.  
  282.     SelectedNode = ArrayChebyshevNodes;
  283.     Selected_steps = Array_steps_cheb;
  284.  
  285.     /*---------------------------------СЛАУ - matrix_coeffs -------------------------------------*/
  286.     double** matrix_coeffs;
  287.     matrix_coeffs = new double* [CountSegments + 1];
  288.     for (i = 0; i < CountSegments + 1; i++)
  289.         matrix_coeffs[i] = new double[3];
  290.  
  291.     get_matrix_coeffs(&Func, matrix_coeffs, Array_steps_uni, ArrayUniformNodes, Initial, End, CountSegments);
  292.  
  293.     /*---------------------------------Прогонка - запись в x_massiv -------------------------------------*/
  294.     double* x_massiv = new double[CountSegments + 1];
  295.     tridiagonal_matrix_algorithm(matrix_coeffs, Array_steps_uni, ArrayUniformNodes, x_massiv, CountSegments);
  296.  
  297.     /*---------------------------------Графики -------------------------------------*/
  298.     tables_in_file(&Func, ArrayUniformNodes, Countdots, CountSegments, Initial, End, Array_steps_uni, x_massiv);
  299.  
  300.     /*---------------------------------Вывод в консоль значений -------------------------------------*/
  301.  
  302.     cout << "Проверка А: " << approximate_derivative_1(Initial, Array_steps_uni, x_massiv, ArrayUniformNodes, CountSegments) << endl;
  303.     cout << "Проверка B: " << approximate_derivative_2(End, Array_steps_uni, x_massiv, ArrayUniformNodes, CountSegments) << endl;
  304.     //Шаги
  305.     cout << endl;
  306.     for (i = 1; i <= CountSegments; i++) {
  307.         cout << "h_" << i << ": " << Selected_steps[i] << endl;
  308.     }
  309.  
  310.     cout << endl << "Cетка:  " << endl;
  311.     for (int i = 0; i < CountSegments + 1; i++)
  312.  
  313.         cout << "(" << ArrayUniformNodes[i].x << ":" << ArrayUniformNodes[i].y << ")" << endl;
  314.     cout << endl;
  315.  
  316.  
  317.     //Гаммы
  318.     for (i = 0; i < CountSegments + 1; i++)
  319.         cout << "g_" << i << ": " << x_massiv[i] << endl;
  320.     cout << endl;
  321.  
  322.     //Значение сплайна в узлах
  323.     for (i = 0; i < CountSegments; i++)
  324.         cout << "Spline in x_" << i << " " << Spline(ArrayUniformNodes[i].x, Array_steps_uni, x_massiv, ArrayUniformNodes, CountSegments) << endl;
  325.     cout << "Spline in x_" << CountSegments << " " << Spline(ArrayUniformNodes[CountSegments].x, Array_steps_uni, x_massiv, ArrayUniformNodes, CountSegments) << endl;
  326.     cout << Spline(-0.5, Array_steps_uni, x_massiv, ArrayUniformNodes, 4) << endl;
  327.  
  328.     cout << endl;
  329.     system("pause");
  330.     return 0;
  331. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement