Advertisement
vadimk772336

Untitled

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