vadimk772336

Untitled

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