vadimk772336

Untitled

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