vadimk772336

Untitled

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