vadimk772336

Untitled

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