Advertisement
coloriot

HA25_2

Sep 27th, 2024
20
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 12.49 KB | None | 0 0
  1. #include <iostream>
  2. #include <string>
  3.  
  4. // Улучшение класса матриц, с exception, операциями с матрицами и теперь с double вместо int
  5.  
  6. using namespace std;
  7.  
  8. // Исключение для разных размерностей матриц
  9. class Error_invalid_size {
  10.     string message;
  11. public:
  12.     Error_invalid_size() : message("Разные размерности!") {}
  13.     ~Error_invalid_size() {}
  14.     void what() {
  15.         cout << message << endl;
  16.     }
  17. };
  18.  
  19. // Исключение для неквадратных матриц
  20. class Error_non_square_matrix {
  21.     string message;
  22. public:
  23.     Error_non_square_matrix() : message("Матрица не квадратная!") {}
  24.     ~Error_non_square_matrix() {}
  25.     void what() {
  26.         cout << message << endl;
  27.     }
  28. };
  29.  
  30. // Исключение для матриц, не являющихся положительно определенными
  31. class Error_not_positive_definite {
  32.     string message;
  33. public:
  34.     Error_not_positive_definite() : message("Матрица не является положительно определенной!") {}
  35.     ~Error_not_positive_definite() {}
  36.     void what() {
  37.         cout << message << endl;
  38.     }
  39. };
  40.  
  41. class Matrix {
  42. private:
  43.     double** matrix;
  44.     int rows;
  45.     int cols;
  46.  
  47.     // Находим определитель рекурсией
  48.     double determinant_recursive(double** mat, int n) {
  49.         if (n == 1) {
  50.             return mat[0][0];
  51.         }
  52.         if (n == 2) {
  53.             return mat[0][0]*mat[1][1] - mat[0][1]*mat[1][0];
  54.         }
  55.         double det = 0;
  56.         for (int p = 0; p < n; p++) {
  57.             double** sub_mat = new double*[n-1];
  58.             for (int i = 0; i < n-1; i++) {
  59.                 sub_mat[i] = new double[n-1];
  60.             }
  61.             for (int i = 1; i < n; i++) {
  62.                 int colIndex = 0;
  63.                 for (int j = 0; j < n; j++) {
  64.                     if (j == p) continue;
  65.                     sub_mat[i-1][colIndex] = mat[i][j];
  66.                     colIndex++;
  67.                 }
  68.             }
  69.             double sub_det = determinant_recursive(sub_mat, n-1);
  70.             det += (p%2==0 ? 1 : -1) * mat[0][p] * sub_det;
  71.             for (int i = 0; i < n-1; i++) {
  72.                 delete[] sub_mat[i];
  73.             }
  74.             delete[] sub_mat;
  75.         }
  76.         return det;
  77.     }
  78.  
  79.     double my_abs(double x) {
  80.         return x >= 0 ? x : -x;
  81.     }
  82.  
  83.     // Для поиска квадратных корней
  84.     double my_sqrt(double x) {
  85.         if (x < 0) {
  86.             return 0;
  87.         }
  88.         double guess = x / 2.0;
  89.         double epsilon = 1e-10;
  90.         while (my_abs(guess * guess - x) > epsilon) {
  91.             guess = (guess + x / guess) / 2.0;
  92.         }
  93.         return guess;
  94.     }
  95.  
  96. public:
  97.     Matrix(int new_rows, int new_cols) {
  98.         this->rows = new_rows;
  99.         this->cols = new_cols;
  100.         this->matrix = new double*[new_rows];
  101.         for (int i = 0; i < this->rows; ++i) {
  102.             matrix[i] = new double[new_cols];
  103.         }
  104.         for (int i = 0; i < this->rows; ++i) {
  105.             for (int j = 0; j < this->cols; ++j) {
  106.                 matrix[i][j] = 0.0;
  107.             }
  108.         }
  109.     }
  110.  
  111.     Matrix(const Matrix& other) {
  112.         rows = other.rows;
  113.         cols = other.cols;
  114.         matrix = new double*[rows];
  115.         for (int i = 0; i < rows; ++i) {
  116.             matrix[i] = new double[cols];
  117.             for (int j = 0; j < cols; ++j) {
  118.                 matrix[i][j] = other.matrix[i][j];
  119.             }
  120.         }
  121.     }
  122.  
  123.     ~Matrix() {
  124.         for (int i = 0; i < this->rows; ++i) {
  125.             delete[] this->matrix[i];
  126.         }
  127.         delete[] this->matrix;
  128.     }
  129.  
  130.     Matrix operator+ (const Matrix& other) {
  131.         if (this->rows != other.rows || this->cols != other.cols) {
  132.             throw Error_invalid_size();
  133.         }
  134.         Matrix new_matrix(this->rows, this->cols);
  135.         for (int i = 0; i < this->rows; ++i) {
  136.             for (int j = 0; j < this->cols; ++j) {
  137.                 new_matrix.matrix[i][j] = this->matrix[i][j] + other.matrix[i][j];
  138.             }
  139.         }
  140.         return new_matrix;
  141.     }
  142.  
  143.     Matrix operator- (const Matrix& other) {
  144.         if (this->rows != other.rows || this->cols != other.cols) {
  145.             throw Error_invalid_size();
  146.         }
  147.         Matrix new_matrix(this->rows, this->cols);
  148.         for (int i = 0; i < this->rows; ++i) {
  149.             for (int j = 0; j < this->cols; ++j) {
  150.                 new_matrix.matrix[i][j] = this->matrix[i][j] - other.matrix[i][j];
  151.             }
  152.         }
  153.         return new_matrix;
  154.     }
  155.  
  156.     Matrix operator* (const Matrix& other) {
  157.         if (this->cols != other.rows) {
  158.             throw Error_invalid_size();
  159.         }
  160.         Matrix result(this->rows, other.cols);
  161.         for (int i = 0; i < this->rows; ++i) {
  162.             for (int j = 0; j < other.cols; ++j) {
  163.                 result.matrix[i][j] = 0.0;
  164.                 for (int k = 0; k < this->cols; ++k) {
  165.                     result.matrix[i][j] += this->matrix[i][k] * other.matrix[k][j];
  166.                 }
  167.             }
  168.         }
  169.         return result;
  170.     }
  171.  
  172.     Matrix operator* (double scalar) {
  173.         Matrix new_matrix(this->rows, this->cols);
  174.         for (int i = 0; i < this->rows; ++i) {
  175.             for (int j = 0; j < this->cols; ++j) {
  176.                 new_matrix.matrix[i][j] = this->matrix[i][j] * scalar;
  177.             }
  178.         }
  179.         return new_matrix;
  180.     }
  181.  
  182.     friend Matrix operator* (double scalar, const Matrix& mat) {
  183.         Matrix new_matrix(mat.rows, mat.cols);
  184.         for (int i = 0; i < mat.rows; ++i) {
  185.             for (int j = 0; j < mat.cols; ++j) {
  186.                 new_matrix.matrix[i][j] = scalar * mat.matrix[i][j];
  187.             }
  188.         }
  189.         return new_matrix;
  190.     }
  191.  
  192.     // Произведение Адамара
  193.     Matrix operator% (const Matrix& other) {
  194.         if (this->rows != other.rows || this->cols != other.cols) {
  195.             throw Error_invalid_size();
  196.         }
  197.         Matrix new_matrix(this->rows, this->cols);
  198.         for (int i = 0; i < this->rows; ++i) {
  199.             for (int j = 0; j < this->cols; ++j) {
  200.                 new_matrix.matrix[i][j] = this->matrix[i][j] * other.matrix[i][j];
  201.             }
  202.         }
  203.         return new_matrix;
  204.     }
  205.  
  206.     Matrix transpose() {
  207.         Matrix new_matrix(this->cols, this->rows);
  208.         for (int i = 0; i < this->rows; ++i) {
  209.             for (int j = 0; j < this->cols; ++j) {
  210.                 new_matrix.matrix[j][i] = this->matrix[i][j];
  211.             }
  212.         }
  213.         return new_matrix;
  214.     }
  215.  
  216.     double determinant() {
  217.         if (this->rows != this->cols) {
  218.             throw Error_non_square_matrix();
  219.         }
  220.         return determinant_recursive(this->matrix, this->rows);
  221.     }
  222.  
  223.     // След матрицы
  224.     double trace() {
  225.         if (this->rows != this->cols) {
  226.             throw Error_non_square_matrix();
  227.         }
  228.         double sum = 0.0;
  229.         for (int i = 0; i < this->rows; ++i) {
  230.             sum += this->matrix[i][i];
  231.         }
  232.         return sum;
  233.     }
  234.  
  235.     // Разложение Холецкого
  236.     Matrix cholesky() {
  237.         if (this->rows != this->cols) {
  238.             throw Error_non_square_matrix();
  239.         }
  240.         int n = this->rows;
  241.         Matrix L(n, n);
  242.         for (int i = 0; i < n; i++) {
  243.             for (int j = 0; j <= i; j++) {
  244.                 double sum = 0.0;
  245.                 if (j == i) {
  246.                     for (int k = 0; k < j; k++) {
  247.                         sum += L.matrix[j][k] * L.matrix[j][k];
  248.                     }
  249.                     double val = this->matrix[j][j] - sum;
  250.                     if (val <= 0) {
  251.                         throw Error_not_positive_definite();
  252.                     }
  253.                     L.matrix[j][j] = my_sqrt(val);
  254.                 } else {
  255.                     for (int k = 0; k < j; k++) {
  256.                         sum += L.matrix[i][k] * L.matrix[j][k];
  257.                     }
  258.                     L.matrix[i][j] = (1.0 / L.matrix[j][j]) * (this->matrix[i][j] - sum);
  259.                 }
  260.                 L.matrix[j][i] = 0.0; // Обеспечиваем нули в верхней треугольной части
  261.             }
  262.         }
  263.         return L;
  264.     }
  265.  
  266.     double get(int i, int j) const {
  267.         if (i < 0 || i >= this->rows || j < 0 || j >= this->cols) {
  268.             throw std::out_of_range("Индекс вне диапазона!");
  269.         }
  270.         return this->matrix[i][j];
  271.     }
  272.  
  273.     void set(int i, int j, double value) {
  274.         if (i < 0 || i >= this->rows || j < 0 || j >= this->cols) {
  275.             throw std::out_of_range("Индекс вне диапазона!");
  276.         }
  277.         this->matrix[i][j] = value;
  278.     }
  279.  
  280.     // Поиск обратной матрицы
  281.     Matrix invert() {
  282.         if (this->rows != this->cols) {
  283.             throw Error_non_square_matrix();
  284.         }
  285.         int n = this->rows;
  286.         Matrix aug(n, 2 * n);
  287.         // Расширенная матрица [A | I]
  288.         for (int i = 0; i < n; i++) {
  289.             for (int j = 0; j < n; j++) {
  290.                 aug.set(i, j, this->get(i, j));
  291.             }
  292.             for (int j = n; j < 2 * n; j++) {
  293.                 aug.set(i, j, (i == j - n) ? 1.0 : 0.0);
  294.             }
  295.         }
  296.         // Исключения по Гауссу-Джордану
  297.         for (int i = 0; i < n; i++) {
  298.             // Точка опоры
  299.             double pivot = aug.get(i, i);
  300.             if (pivot == 0) {
  301.                 throw std::runtime_error("Матрица является вырожденной и не может быть инвертирована.");
  302.             }
  303.             // Нормализуем
  304.             for (int j = 0; j < 2 * n; j++) {
  305.                 aug.set(i, j, aug.get(i, j) / pivot);
  306.             }
  307.             // Убираем другие строки
  308.             for (int k = 0; k < n; k++) {
  309.                 if (k != i) {
  310.                     double factor = aug.get(k, i);
  311.                     for (int j = 0; j < 2 * n; j++) {
  312.                         aug.set(k, j, aug.get(k, j) - factor * aug.get(i, j));
  313.                     }
  314.                 }
  315.             }
  316.         }
  317.         // Извлекаем обратную матрицу
  318.         Matrix inv(n, n);
  319.         for (int i = 0; i < n; i++) {
  320.             for (int j = n; j < 2 * n; j++) {
  321.                 inv.set(i, j - n, aug.get(i, j));
  322.             }
  323.         }
  324.         return inv;
  325.     }
  326.  
  327.     void print() const {
  328.         for (int i = 0; i < this->rows; ++i) {
  329.             for (int j = 0; j < this->cols; ++j) {
  330.                 cout << matrix[i][j] << ' ';
  331.             }
  332.             cout << '\n';
  333.         }
  334.     }
  335. };
  336.  
  337. int main() {
  338.     try {
  339.         Matrix mat1(2, 2);
  340.         mat1.set(0, 0, 4.0);
  341.         mat1.set(0, 1, 12.0);
  342.         mat1.set(1, 0, 12.0);
  343.         mat1.set(1, 1, 37.0);
  344.  
  345.         Matrix mat2(2, 2);
  346.         mat2.set(0, 0, 3.0);
  347.         mat2.set(0, 1, 4.0);
  348.         mat2.set(1, 0, 5.0);
  349.         mat2.set(1, 1, 6.0);
  350.  
  351.         Matrix sum = mat1 + mat2;
  352.         cout << "Сумма:\n";
  353.         sum.print();
  354.  
  355.         Matrix diff = mat1 - mat2;
  356.         cout << "Разность:\n";
  357.         diff.print();
  358.  
  359.         Matrix prod = mat1 * mat2;
  360.         cout << "Умножение:\n";
  361.         prod.print();
  362.  
  363.         Matrix scalar_mul = mat1 * 2.0;
  364.         cout << "Скалярное произведение на 2:\n";
  365.         scalar_mul.print();
  366.  
  367.         Matrix hadamard = mat1 % mat2;
  368.         cout << "Произведение Адамара:\n";
  369.         hadamard.print();
  370.  
  371.         Matrix transposed = mat1.transpose();
  372.         cout << "Транспонирование:\n";
  373.         transposed.print();
  374.  
  375.         double det = mat1.determinant();
  376.         cout << "Определитель: " << det << endl;
  377.  
  378.         double tr = mat1.trace();
  379.         cout << "След: " << tr << endl;
  380.  
  381.         Matrix chol = mat1.cholesky();
  382.         cout << "Разложение Холецкого:\n";
  383.         chol.print();
  384.  
  385.         Matrix inv = mat1.invert();
  386.         cout << "Обратная матрица:\n";
  387.         inv.print();
  388.  
  389.     } catch (Error_invalid_size& e) {
  390.         e.what();
  391.     } catch (Error_non_square_matrix& e) {
  392.         e.what();
  393.     } catch (Error_not_positive_definite& e) {
  394.         e.what();
  395.     } catch (std::exception& e) {
  396.         cout << e.what() << endl;
  397.     }
  398.     return 0;
  399. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement