Advertisement
Guest User

Untitled

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