vadimk772336

Untitled

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