Xsufu

6.3

Apr 15th, 2021 (edited)
348
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 13.24 KB | None | 0 0
  1. #include <iostream> //подключение библиотеки ввода и вывода на консоль
  2. #include <cmath> //подключение библиотеки математических операций
  3. #include <fstream> //подключение библиотеки записи и чтения с файла
  4. #include "windows.h" //подключение библиотеки русского языка
  5. #include <string> //подключаем библиотеку для использования строк
  6.  
  7. using namespace std; //использование пространственных имён стд
  8.  
  9. double* function(double, double, int, double, double); //функция вычисления коэффициентов уравнения
  10. void recordInFile(double**, int, int); //функция ввода в файл
  11. double* choosingEquation(); //функция выбора уравнения с консоли
  12. void konechRazn(int,int,double,double,double,double); //метод конечных разностей
  13. double* progonka(double**, int); //метод прогонки для решения составленной матрицы
  14. double* first(int, double , double ); //функция для вычисления коэффициентов начального уравнения
  15. double* last(int, double, double); //функция для вычисления коэффициентов конечного уравнения
  16.  
  17. void recordInFile(double** table, int cols, int rows) { //функция записи в файл данных
  18.  
  19.     ofstream resultsForReport; // переменная для записи в файл
  20.     resultsForReport.open("results" + to_string(rows - 1) + ".txt", ofstream::app); //открываем файл для записи вычисленных значений
  21.  
  22.     for (int a = 0; a < rows; a++) { // записываем переменные в цикле
  23.         resultsForReport << endl; // пишем переменные с новой строки
  24.         for (int b = 0; b < cols; b++) {
  25.             resultsForReport << table[a][b]; //записываем переменную
  26.             if (b < cols - 1) // не добавляем пробел после числа
  27.                 resultsForReport << " ";
  28.         }
  29.     }
  30.     resultsForReport << endl << "END"; //добавляем слово конец после записы таблицы переменных
  31.     resultsForReport.close(); //закрываем файл для записи
  32. }
  33.  
  34. double* choosingEquation() { // функция выбора уравнения с консоли
  35.     double endX, nachX, nach, uravn = 0, nach2 = 0; // переменные конца промежутка, начала промежутка, начального значения, номера уравнения
  36.     int delenia = 2; //изначальное количество делений
  37.     cout << "Выберите уравнение: " << endl << "1. u''=u-e^(t/2)+2"; //вывод текста на консоль
  38.     cout << endl << "2. -(1/(3+t))*u''-t*u'+ln(2+t)*u=1-t/2"; //вывод текста на консоль
  39.     while (uravn < 1 || uravn>2) //проверяем, есть ли у нас это уравнение
  40.         cin >> uravn; // ввод с консоли номера уравнения
  41.     switch ((int)uravn) { // в зависимости от выбора уравнения у него разные начальные значения
  42.     case 1: nach = 0; nach2 = -1; nachX = 0; endX = 1; break;  // при первом уравнении
  43.     case 2: nach = 4; nach2 = 4; nachX = -1; endX = 1; break; // при втором уравнении
  44.     }
  45.     double equation[6]{ uravn,delenia,nachX,endX,nach,nach2}; // передаём все значения в массиве
  46.     return equation; //возвращаем массив со значениями в место вызова
  47. }
  48.  
  49. int main() { // главная функция - с неё начинается выполнение программы
  50.     SetConsoleOutputCP(1251); // говорим программе, что вывод текста ещё и на русском языке
  51.     double* equation = choosingEquation();//получаем новые значения
  52.     konechRazn(equation[0], equation[1], equation[2], equation[3], equation[4], equation[5]); //вызываем метод конечных разностей
  53.     return 0; //возвращаем главной функции 0, чтобы она завершилась
  54. }
  55.  
  56. void konechRazn(int uravn, int delenia, double nachX, double endX, double nach, double nach2) { //функция метода конечных разностей
  57.    
  58.     for (int h = 0; h < 5; h++, delenia*=2) { //проходим 3 раза
  59.         double step = abs(nachX - endX) / (double)delenia; //вычисляем шаг
  60.         delenia += 1; //нам нужно и конечное значение
  61.         double** matr = new double* [delenia]; //создаем матрицу под коэффициенты уравнений
  62.         double* answers = new double[delenia]; //создаем массив под ответы
  63.         double** table = new double* [delenia]; //создаем таблицу для графика
  64.         double* tempMas = new double[delenia]; //создаём массив под временные значения
  65.         for (int a = 0; a < delenia; a++) //выделяем место под значения
  66.         {
  67.             matr[a] = new double[4]; //в каждой строке 4 значения
  68.             table[a] = new double[2]; //в таблице два столбца
  69.             table[a][0] = nachX + step * a; //заполняем нашу независимую переменную в таблицу
  70.  
  71.         }
  72.  
  73.         for (int a = 1; a < delenia - 1; a++) {// создаём матрицу
  74.             for (int b = 0; b < 4; b++) { //все 4 столбца
  75.                 matr[a][b] = function(NULL, NULL, uravn, nachX + a * step, step)[b]; //получаем коэффициенты
  76.                 if (a == 1) {
  77.                     tempMas = first(uravn, nachX, step); //получаем коэффициенты первого уравнения
  78.                     matr[0][b] = tempMas[b]; //записываем их в матрицу
  79.                     tempMas = last(uravn, nachX, step); //получаем коэффициенты последнего уравнения
  80.                     matr[delenia - 1][b] = tempMas[b]; //записываем их в матрицу
  81.                 }
  82.  
  83.             }
  84.         }
  85.  
  86.         /* cout << "МАТРИЦА";
  87.         for (int a = 0; a < delenia; a++) { //вывод матрицы на экран
  88.             cout << endl;
  89.             for (int b = 0; b < 4; b++)
  90.                 cout << matr[a][b] << " ";
  91.         } */
  92.  
  93.         tempMas = progonka(matr, delenia);//получаем результаты прогонки
  94.         for (int a = 0; a < delenia; a++) //заполняем полученными значениями наш массив ответов
  95.             answers[a] = tempMas[a];
  96.  
  97.         if (matr[uravn - 1][1] == 0 && matr[uravn - 1][2] == 0 && matr[0][1] == 0 && matr[0][2] == 0) { // в случае, когда у нас нету 1 уравнения и последнего, а значения u[0],u[last]
  98.             answers[0] = matr[0][3]; answers[delenia - 1] = matr[delenia - 1][3];
  99.         }
  100.         else if (matr[uravn - 1][1] == 0 && matr[uravn - 1][2] == 0) // в случае, когда у нас нету последнего уравнения, а значение u[last]
  101.             answers[delenia - 1] = matr[delenia - 1][3];
  102.         else if (matr[0][1] == 0 && matr[0][2] == 0)// в случае, когда у нас нет первого уравнения, а значение u[0]
  103.             answers[0] = matr[0][3];
  104.  
  105.         for (int a = 0; a < delenia; a++) //заполняем таблицу
  106.             table[a][1] = answers[a];
  107.  
  108.         cout << "X     Y"; //выводим на консоль полученную таблицу
  109.         for (int a = 0; a < delenia; a++) //выводим на консоль
  110.             cout << endl << table[a][0] << "    " << table[a][1];
  111.         recordInFile(table, 2, delenia); //записываем в файл
  112.         for (int a = 0; a < delenia; a++)//удаляем массивы для экономии памяти
  113.         {
  114.             delete[] matr[a];
  115.         }
  116.         delete[] matr; //удалаяем указатель на массивы
  117.         delenia -= 1;//вычитаем, чтобы правильно рассчитать деления
  118.     }
  119. }
  120.  
  121.  
  122.  
  123. double* progonka(double** matr, int kolvoUravn) {// вычисляем значения прогонки
  124.     double* A = new double[kolvoUravn]; double* B = new double[kolvoUravn]; //место под значения A и B
  125.     double* C = new double[kolvoUravn]; double* F = new double[kolvoUravn]; //место под значения C и F
  126.     double* beta = new double[kolvoUravn+1]; double* alpha = new double[kolvoUravn + 1]; //место под значения alpha и beta
  127.     double* answers = new double[kolvoUravn+1];//метсто под ответы
  128.  
  129.     C[0] = matr[0][0]; B[0] = matr[0][1]; F[0] = matr[0][3]; //C1,B1,F1
  130.     alpha[1] = -B[0] / C[0]; beta[1] = F[0] / C[0];//a1,b1
  131.  
  132.     if (matr[kolvoUravn - 1][1] == 0 && matr[kolvoUravn - 1][2] == 0 && matr[0][1] == 0 && matr[0][2] == 0) { //если у нас нет конечных уравнений, а значения
  133.         answers[kolvoUravn - 1] = matr[kolvoUravn - 1][3];//записываем последний ответ как ответ последнего уравнения в матрице
  134.         for (int i = 1; i < kolvoUravn - 1; i++) { //вычисляем A,C,B,F,a,b
  135.             A[i] = matr[i][0]; C[i] = matr[i][1]; B[i] = matr[i][2]; F[i] = matr[i][3];
  136.             alpha[i + 1] = -B[i] / (A[i] * alpha[i] + C[i]);
  137.             beta[i + 1] = (F[i] - A[i] * beta[i]) / (A[i] * alpha[i] + C[i]);
  138.         }
  139.         for (int a = kolvoUravn-1; a > 1; a--) { //находим ответы обратным ходом прогонки
  140.             answers[a - 1] = alpha[a] * answers[a] + beta[a];
  141.         }
  142.     }
  143.     else if (matr[0][1] == 0 && matr[0][2] == 0 || matr[kolvoUravn - 1][1] == 0 && matr[kolvoUravn - 1][2] == 0) //
  144.     {
  145.         answers[0] = matr[0][3];
  146.         for (int i = 1; i < kolvoUravn - 1; i++) {
  147.             A[i] = matr[i][0]; C[i] = matr[i][1]; B[i] = matr[i][2]; F[i] = matr[i][3];
  148.             alpha[i + 1] = -B[i] / (A[i] * alpha[i] + C[i]);
  149.             beta[i + 1] = (F[i] - A[i] * beta[i]) / (A[i] * alpha[i] + C[i]);
  150.         }
  151.         answers[kolvoUravn - 1] = beta[kolvoUravn];
  152.         for (int a = 1; a < kolvoUravn + 1; a++)
  153.  
  154.         for (int a = kolvoUravn - 1; a > 1; a--) {
  155.             answers[a - 1] = alpha[a] * answers[a] + beta[a];
  156.         }
  157.     }
  158.     else { //если у нас есть конечные уравнения
  159.         for (int i = 1; i < kolvoUravn; i++) { //вычисляем A,B,C,F,a,b
  160.             A[i] = matr[i][0]; C[i] = matr[i][1]; B[i] = matr[i][2]; F[i] = matr[i][3];
  161.             alpha[i + 1] = -B[i] / (A[i] * alpha[i] + C[i]);
  162.             beta[i + 1] = (F[i] - A[i] * beta[i]) / (A[i] * alpha[i] + C[i]);
  163.         }
  164.         answers[kolvoUravn-1] = beta[kolvoUravn]; // X[last]=b[last+1]
  165.         for (int a = kolvoUravn-1; a > 0; a--) { //находим ответы обратным ходом прогонки
  166.             answers[a - 1] = alpha[a] * answers[a] + beta[a];
  167.             cout << answers[a - 1] << "= " << alpha[a] << "*" << answers[a] << "+" << beta[a] << endl;
  168.         }
  169.     }
  170.     return answers; //возвращаем ответы в место вызова
  171. }
  172.  
  173. double* first(int Number, double t, double step) //функция первого уравнения
  174. {
  175.     double* uravn = new double[4]; //место под коэффициенты
  176.     switch (Number) { //в зависимости от выбранного уравнения
  177.     case 1:  //при первом уравнении
  178.         uravn[0] = 1; uravn[1] = 0; uravn[2] = 0; uravn[3] = 1;
  179.     break;
  180.     case 2: //при втором уравнении
  181.         uravn[0] = -1/step; uravn[1] = 1 / step; uravn[2] = 0; uravn[3] = 0;
  182.     break;
  183.     }
  184.     return uravn; //возвращаем вычисленные коэффициенты
  185. }
  186.  
  187. double* last(int Number, double t, double step) //функция последнего уравнения
  188. {
  189.     double* uravn = new double[4];//место под коэффициенты
  190.     switch (Number) { //в зависимости от выбранного уравнения
  191.     case 1: //при первом уравнении
  192.         uravn[0] = 1; uravn[1] = 0; uravn[2] = 0; uravn[3] = 0;
  193.         break;
  194.     case 2:  //при втором уравнении
  195.         uravn[0] = -1; uravn[1] = (1 + step * 1 / 2.0); uravn[2] = 0; uravn[3] = 0;
  196.         break;
  197.     }
  198.     return uravn; //возвращаем вычисленные коэффициенты
  199. }
  200.  
  201.  
  202. double* function(double x, double y, int Number, double t, double step) {//функция вычисления коэффициентов
  203.     double* uravn = new double[4]; //место под вычисленные коэффициенты
  204.     switch (Number) { //в зависимости от номера уравнения, у нас разные формулы для вычисления коэффициентов
  205.     case 1:  //при первом уравнении
  206.         uravn[0] = 1; uravn[1] = -2 - pow(step, 2)*pow(t,3);
  207.         uravn[2] = 1; uravn[3] = pow(step, 2) * cos(t);
  208.         break;
  209.     case 2:  //при втором уравнении
  210.         uravn[0] = -2 - t * (3 + t) * step; uravn[1] = 4 + 2 * pow(step, 2) * (3 + t) * log(2 + t);
  211.         uravn[2] = -2 - t * (3 + t) * step; uravn[3] = (1 - t / 2.0) * (2 * pow(step, 2) * (3 + t));
  212.         break; //2-ое уравнение 1 ОДУ 2 порядка
  213.     }
  214.     return uravn; //возвращаем полученное значение в место вызова
  215. }
Add Comment
Please, Sign In to add comment