RobertDeMilo

Вычисление обратной матрицы

Jul 27th, 2025
155
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 5.90 KB | None | 0 0
  1. #include <stdio.h>
  2. #include <stdlib.h>
  3.  
  4. void input(double ***matrix, int *n, int *m) {
  5.     scanf("%d %d", n, m);
  6.     *matrix = (double **)malloc(*n * sizeof(double *));
  7.     for (int i = 0; i < *n; i++) {
  8.         (*matrix)[i] = (double *)malloc(*m * sizeof(double));
  9.         for (int j = 0; j < *m; j++) {
  10.             scanf("%lf", &(*matrix)[i][j]);
  11.         }
  12.     }
  13. }
  14.  
  15. void output(double **matrix, int n, int m) {
  16.     for (int i = 0; i < n; i++) {
  17.         for (int j = 0; j < m; j++) {
  18.             printf("%.6lf", matrix[i][j]);
  19.             if (j < m - 1) {
  20.                 printf(" ");
  21.             }
  22.         }
  23.         if (i < n - 1) {
  24.             printf("\n");
  25.         }
  26.     }
  27. }
  28.  
  29. void free_matrix(double **matrix, int n) {
  30.     for (int i = 0; i < n; i++) {
  31.         free(matrix[i]);
  32.     }
  33.     free(matrix);
  34. }
  35.  
  36. double determinant(double **matrix, int n) {
  37.     double det = 1.0;
  38.     double **temp = (double **)malloc(n * sizeof(double *));
  39.     for (int i = 0; i < n; i++) {
  40.         temp[i] = (double *)malloc(n * sizeof(double));
  41.         for (int j = 0; j < n; j++) {
  42.             temp[i][j] = matrix[i][j];
  43.         }
  44.     }
  45.  
  46.     for (int i = 0; i < n; i++) {
  47.         if (temp[i][i] == 0.0) {
  48.             int swap_row = -1;
  49.             for (int k = i + 1; k < n; k++) {
  50.                 if (temp[k][i] != 0.0) {
  51.                     swap_row = k;
  52.                     break;
  53.                 }
  54.             }
  55.             if (swap_row == -1) {
  56.                 free_matrix(temp, n);
  57.                 return 0.0;
  58.             }
  59.             double *tmp = temp[i];
  60.             temp[i] = temp[swap_row];
  61.             temp[swap_row] = tmp;
  62.             det *= -1.0;
  63.         }
  64.  
  65.         det *= temp[i][i];
  66.  
  67.         for (int j = i + 1; j < n; j++) {
  68.             double factor = temp[j][i] / temp[i][i];
  69.             for (int k = i; k < n; k++) {
  70.                 temp[j][k] -= factor * temp[i][k];
  71.             }
  72.         }
  73.     }
  74.  
  75.     free_matrix(temp, n);
  76.     return det;
  77. }
  78.  
  79. void cofactor(double **matrix, double **cof, int n, int row, int col) {
  80.     int i = 0, j = 0;
  81.     for (int r = 0; r < n; r++) {
  82.         for (int c = 0; c < n; c++) {
  83.             if (r != row && c != col) {
  84.                 cof[i][j++] = matrix[r][c];
  85.                 if (j == n - 1) {
  86.                     j = 0;
  87.                     i++;
  88.                 }
  89.             }
  90.         }
  91.     }
  92. }
  93.  
  94. void adjoint(double **matrix, double **adj, int n) {
  95.     if (n == 1) {
  96.         adj[0][0] = 1.0;
  97.         return;
  98.     }
  99.  
  100.     double **temp = (double **)malloc(n * sizeof(double *));
  101.     for (int i = 0; i < n; i++) {
  102.         temp[i] = (double *)malloc(n * sizeof(double));
  103.     }
  104.  
  105.     for (int i = 0; i < n; i++) {
  106.         for (int j = 0; j < n; j++) {
  107.             cofactor(matrix, temp, n, i, j);
  108.             double det = determinant(temp, n - 1);
  109.             adj[j][i] = ((i + j) % 2 == 0 ? 1 : -1) * det;
  110.         }
  111.     }
  112.  
  113.     free_matrix(temp, n);
  114. }
  115.  
  116. void invert(double **matrix, int n, int m) {
  117.     double det = determinant(matrix, n);
  118.     if (det == 0.0) {
  119.         printf("n/a");
  120.         return;
  121.     }
  122.  
  123.     double **adj = (double **)malloc(n * sizeof(double *));
  124.     for (int i = 0; i < n; i++) {
  125.         adj[i] = (double *)malloc(n * sizeof(double));
  126.     }
  127.  
  128.     adjoint(matrix, adj, n);
  129.  
  130.     double **inv = (double **)malloc(n * sizeof(double *));
  131.     for (int i = 0; i < n; i++) {
  132.         inv[i] = (double *)malloc(n * sizeof(double));
  133.         for (int j = 0; j < n; j++) {
  134.             inv[i][j] = adj[i][j] / det;
  135.         }
  136.     }
  137.  
  138.     output(inv, n, m);
  139.  
  140.     free_matrix(adj, n);
  141.     free_matrix(inv, n);
  142. }
  143.  
  144. int main() {
  145.     double **matrix;
  146.     int n, m;
  147.     input(&matrix, &n, &m);
  148.  
  149.     if (n != m) {
  150.         printf("n/a");
  151.     } else {
  152.         invert(matrix, n, m);
  153.     }
  154.  
  155.     free_matrix(matrix, n);
  156.     return 0;
  157. }
  158. .....................................................................................................................................
  159. Входные данные
  160. 3 3
  161. 1 0.5 1
  162. 4 1 2
  163. 3 2 2
  164. Выходные данные
  165. -1.000000 0.500000 0.000000
  166. -1.000000 -0.500000 1.000000
  167. 2.500000 -0.250000 -0.500000
  168. .....................................................................................................................................
  169. Преимущества и недостатки метода:
  170. ✅ Точность: Метод даёт точное решение (без итерационных погрешностей, как в численных методах).
  171. ✅ Понятность: Алгоритм легко реализуется на основе операций с определителями.
  172.  
  173. ❌ Вычислительная сложность: Метод требует O(n!) операций для вычисления определителей (очень медленно для больших матриц).
  174. ❌ Неустойчивость: При работе с матрицами, близкими к вырожденным, возможны ошибки округления.
  175. Альтернативные методы:
  176.  
  177. Метод Гаусса-Жордана (более эффективный для больших матриц).
  178.  
  179. LU-разложение (ускоряет вычисления для множества матриц одного размера).
  180.  
  181. Итерационные методы (например, метод Якоби) для разреженных матриц.
  182.  
  183. Вывод: В этой программе обратная матрица находится классическим методом присоединённой матрицы, что хорошо подходит для учебных целей и матриц небольшого размера. Для реальных задач с большими матрицами лучше использовать более оптимизированные методы.
Advertisement
Add Comment
Please, Sign In to add comment