Advertisement
vadimk772336

Untitled

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