vadimk772336

Untitled

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