Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #include <stdio.h>
- #include <stdlib.h>
- void input(double ***matrix, int *n, int *m) {
- scanf("%d %d", n, m);
- *matrix = (double **)malloc(*n * sizeof(double *));
- for (int i = 0; i < *n; i++) {
- (*matrix)[i] = (double *)malloc(*m * sizeof(double));
- for (int j = 0; j < *m; j++) {
- scanf("%lf", &(*matrix)[i][j]);
- }
- }
- }
- void output(double **matrix, int n, int m) {
- for (int i = 0; i < n; i++) {
- for (int j = 0; j < m; j++) {
- printf("%.6lf", matrix[i][j]);
- if (j < m - 1) {
- printf(" ");
- }
- }
- if (i < n - 1) {
- printf("\n");
- }
- }
- }
- void free_matrix(double **matrix, int n) {
- for (int i = 0; i < n; i++) {
- free(matrix[i]);
- }
- free(matrix);
- }
- double determinant(double **matrix, int n) {
- double det = 1.0;
- double **temp = (double **)malloc(n * sizeof(double *));
- for (int i = 0; i < n; i++) {
- temp[i] = (double *)malloc(n * sizeof(double));
- for (int j = 0; j < n; j++) {
- temp[i][j] = matrix[i][j];
- }
- }
- for (int i = 0; i < n; i++) {
- if (temp[i][i] == 0.0) {
- int swap_row = -1;
- for (int k = i + 1; k < n; k++) {
- if (temp[k][i] != 0.0) {
- swap_row = k;
- break;
- }
- }
- if (swap_row == -1) {
- free_matrix(temp, n);
- return 0.0;
- }
- double *tmp = temp[i];
- temp[i] = temp[swap_row];
- temp[swap_row] = tmp;
- det *= -1.0;
- }
- det *= temp[i][i];
- for (int j = i + 1; j < n; j++) {
- double factor = temp[j][i] / temp[i][i];
- for (int k = i; k < n; k++) {
- temp[j][k] -= factor * temp[i][k];
- }
- }
- }
- free_matrix(temp, n);
- return det;
- }
- void cofactor(double **matrix, double **cof, int n, int row, int col) {
- int i = 0, j = 0;
- for (int r = 0; r < n; r++) {
- for (int c = 0; c < n; c++) {
- if (r != row && c != col) {
- cof[i][j++] = matrix[r][c];
- if (j == n - 1) {
- j = 0;
- i++;
- }
- }
- }
- }
- }
- void adjoint(double **matrix, double **adj, int n) {
- if (n == 1) {
- adj[0][0] = 1.0;
- return;
- }
- double **temp = (double **)malloc(n * sizeof(double *));
- for (int i = 0; i < n; i++) {
- temp[i] = (double *)malloc(n * sizeof(double));
- }
- for (int i = 0; i < n; i++) {
- for (int j = 0; j < n; j++) {
- cofactor(matrix, temp, n, i, j);
- double det = determinant(temp, n - 1);
- adj[j][i] = ((i + j) % 2 == 0 ? 1 : -1) * det;
- }
- }
- free_matrix(temp, n);
- }
- void invert(double **matrix, int n, int m) {
- double det = determinant(matrix, n);
- if (det == 0.0) {
- printf("n/a");
- return;
- }
- double **adj = (double **)malloc(n * sizeof(double *));
- for (int i = 0; i < n; i++) {
- adj[i] = (double *)malloc(n * sizeof(double));
- }
- adjoint(matrix, adj, n);
- double **inv = (double **)malloc(n * sizeof(double *));
- for (int i = 0; i < n; i++) {
- inv[i] = (double *)malloc(n * sizeof(double));
- for (int j = 0; j < n; j++) {
- inv[i][j] = adj[i][j] / det;
- }
- }
- output(inv, n, m);
- free_matrix(adj, n);
- free_matrix(inv, n);
- }
- int main() {
- double **matrix;
- int n, m;
- input(&matrix, &n, &m);
- if (n != m) {
- printf("n/a");
- } else {
- invert(matrix, n, m);
- }
- free_matrix(matrix, n);
- return 0;
- }
- .....................................................................................................................................
- Входные данные
- 3 3
- 1 0.5 1
- 4 1 2
- 3 2 2
- Выходные данные
- -1.000000 0.500000 0.000000
- -1.000000 -0.500000 1.000000
- 2.500000 -0.250000 -0.500000
- .....................................................................................................................................
- Преимущества и недостатки метода:
- ✅ Точность: Метод даёт точное решение (без итерационных погрешностей, как в численных методах).
- ✅ Понятность: Алгоритм легко реализуется на основе операций с определителями.
- ❌ Вычислительная сложность: Метод требует O(n!) операций для вычисления определителей (очень медленно для больших матриц).
- ❌ Неустойчивость: При работе с матрицами, близкими к вырожденным, возможны ошибки округления.
- Альтернативные методы:
- Метод Гаусса-Жордана (более эффективный для больших матриц).
- LU-разложение (ускоряет вычисления для множества матриц одного размера).
- Итерационные методы (например, метод Якоби) для разреженных матриц.
- Вывод: В этой программе обратная матрица находится классическим методом присоединённой матрицы, что хорошо подходит для учебных целей и матриц небольшого размера. Для реальных задач с большими матрицами лучше использовать более оптимизированные методы.
Advertisement
Add Comment
Please, Sign In to add comment