Skip to content

Commit 322b769

Browse files
committed
Обратная матрица.
1 parent 3e39179 commit 322b769

9 files changed

+346
-0
lines changed

Diff for: README.md

+1
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,7 @@
5757

5858
- [Класс Triangle, описывающий треугольник](solution-of-triangles/)
5959
- [Определение, является ли треугольник со сторонами a, b, c равнобедренным](is-isosceles-triangle/)
60+
- [Обратная матрица](matrix/invertible-matrix/)
6061

6162
## Физика
6263

Diff for: matrix/invertible-matrix/InvertibleMatrix.dev

+62
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
[Project]
2+
FileName=InvertibleMatrix.dev
3+
Name=InvertibleMatrix
4+
Type=1
5+
Ver=2
6+
ObjFiles=
7+
Includes=
8+
Libs=
9+
PrivateResource=
10+
ResourceIncludes=
11+
MakeIncludes=
12+
Compiler=
13+
CppCompiler=
14+
Linker=
15+
IsCpp=1
16+
Icon=
17+
ExeOutput=
18+
ObjectOutput=
19+
LogOutput=
20+
LogOutputEnabled=0
21+
OverrideOutput=0
22+
OverrideOutputName=
23+
HostApplication=
24+
UseCustomMakefile=0
25+
CustomMakefile=
26+
CommandLine=
27+
Folders=
28+
IncludeVersionInfo=0
29+
SupportXPThemes=0
30+
CompilerSet=0
31+
CompilerSettings=0000000000000000000000000
32+
UnitCount=1
33+
34+
[VersionInfo]
35+
Major=1
36+
Minor=0
37+
Release=0
38+
Build=0
39+
LanguageID=1033
40+
CharsetID=1252
41+
CompanyName=
42+
FileVersion=
43+
FileDescription=Developed using the Dev-C++ IDE
44+
InternalName=
45+
LegalCopyright=
46+
LegalTrademarks=
47+
OriginalFilename=
48+
ProductName=
49+
ProductVersion=
50+
AutoIncBuildNr=0
51+
SyncProduct=1
52+
53+
[Unit1]
54+
FileName=main.cpp
55+
CompileCpp=1
56+
Folder=
57+
Compile=1
58+
Link=1
59+
Priority=1000
60+
OverrideBuildCmd=0
61+
BuildCmd=
62+

Diff for: matrix/invertible-matrix/InvertibleMatrix.layout

+8
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
[Editor_0]
2+
CursorCol=1
3+
CursorRow=214
4+
TopLine=193
5+
LeftChar=1
6+
[Editors]
7+
Order=0
8+
Focused=0

Diff for: matrix/invertible-matrix/Makefile.win

+28
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
# Project: InvertibleMatrix
2+
# Makefile created by Dev-C++ 5.11
3+
4+
CPP = g++.exe
5+
CC = gcc.exe
6+
WINDRES = windres.exe
7+
OBJ = main.o
8+
LINKOBJ = main.o
9+
LIBS = -L"C:/Program Files (x86)/Dev-Cpp/MinGW64/lib" -L"C:/Program Files (x86)/Dev-Cpp/MinGW64/x86_64-w64-mingw32/lib" -static-libgcc
10+
INCS = -I"C:/Program Files (x86)/Dev-Cpp/MinGW64/include" -I"C:/Program Files (x86)/Dev-Cpp/MinGW64/x86_64-w64-mingw32/include" -I"C:/Program Files (x86)/Dev-Cpp/MinGW64/lib/gcc/x86_64-w64-mingw32/4.9.2/include"
11+
CXXINCS = -I"C:/Program Files (x86)/Dev-Cpp/MinGW64/include" -I"C:/Program Files (x86)/Dev-Cpp/MinGW64/x86_64-w64-mingw32/include" -I"C:/Program Files (x86)/Dev-Cpp/MinGW64/lib/gcc/x86_64-w64-mingw32/4.9.2/include" -I"C:/Program Files (x86)/Dev-Cpp/MinGW64/lib/gcc/x86_64-w64-mingw32/4.9.2/include/c++"
12+
BIN = InvertibleMatrix.exe
13+
CXXFLAGS = $(CXXINCS)
14+
CFLAGS = $(INCS)
15+
RM = rm.exe -f
16+
17+
.PHONY: all all-before all-after clean clean-custom
18+
19+
all: all-before $(BIN) all-after
20+
21+
clean: clean-custom
22+
${RM} $(OBJ) $(BIN)
23+
24+
$(BIN): $(OBJ)
25+
$(CPP) $(LINKOBJ) -o $(BIN) $(LIBS)
26+
27+
main.o: main.cpp
28+
$(CPP) -c main.cpp -o main.o $(CXXFLAGS)

Diff for: matrix/invertible-matrix/README.md

+16
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
# Problem Statement
2+
3+
Нужно ввести и вывести n*m матрицу и найти ее обратную матрицу.
4+
5+
# Screenshots
6+
7+
![InvertibleMatrix.exe](screenshot.png)
8+
9+
![inverse matrix](check.png)
10+
11+
# Links
12+
13+
- [Inverse of a square matrix](https://www.cs.rochester.edu/~brown/Crypto/assts/projects/adj.html)
14+
- [C and C++ Program to Find Inverse of a Matrix - The Crazy Programmer](https://www.thecrazyprogrammer.com/2017/02/c-c-program-find-inverse-matrix.html)
15+
- [Inverting matrices - Martin Thoma](https://martin-thoma.com/inverting-matrices/)
16+
- [Wolfram|Alpha Widgets: "inverse matrix" - Free Mathematics Widget](http://www.wolframalpha.com/widgets/view.jsp?id=91ba4a4478a66bee9812b0804b6f9d1b)

Diff for: matrix/invertible-matrix/check.png

19.9 KB
Loading

Diff for: matrix/invertible-matrix/main.cpp

+231
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,231 @@
1+
// Подключение заголовочных файлов
2+
// из стандартной библиотеки:
3+
#include <iostream> // ввод/вывод.
4+
#include <cstdlib> // константа EXIT_SUCCESS.
5+
#include <cmath> // функция pow().
6+
#include <iomanip> // std::setw для задания ширины при выводе; std::fixed и std::setprecision() для форматирования вещественных чисел.
7+
#include <windows.h> // нужно для функций SetConsoleOutputCP и SetConsoleCP.
8+
9+
using namespace std;
10+
11+
// Переход на кириллицу:
12+
void cyrillic() {
13+
// Эти строки нужны для правильного отображения кириллицы:
14+
SetConsoleOutputCP(1251);
15+
SetConsoleCP(1251);
16+
17+
// Также надо изменить шрифт в консоли на Lucida Console.
18+
// Для замены шрифта кликаете правой кнопкой на надписи «Командная строка» окна консоли.
19+
// В открывшемся меню выбираете «Свойства».
20+
// В появившемся окне выбираете вкладку «Шрифт» и там выбираете «Lucida Console».
21+
}
22+
23+
// Выделение памяти под матрицу n*m:
24+
float** matalloc(int n, int m) {
25+
float** mat = new float*[n];
26+
for (int i = 0; i < n; i++) {
27+
mat[i] = new float[m];
28+
for (int j = 0; j < m; j++) {
29+
mat[i][j] = 0;
30+
}
31+
}
32+
return mat;
33+
}
34+
35+
// Освобождение памяти под матрицу:
36+
void matfree(float** mat, int n) {
37+
for (int i = 0; i < n; ++i) {
38+
delete[] mat[i];
39+
}
40+
delete[] mat;
41+
}
42+
43+
// Ввод матрицы:
44+
void matinput(float** mat, int n, int m) {
45+
for (int i = 0; i < n; i++) {
46+
for (int j = 0; j < m; j++) {
47+
cin >> mat[i][j];
48+
}
49+
}
50+
}
51+
52+
// Вывод матрицы:
53+
void matprint(float** mat, int n, int m) {
54+
for (int i = 0; i < n; i++) {
55+
for (int j = 0; j < m; j++) {
56+
cout << std::setw(8) << std::fixed << std::setprecision(2) << mat[i][j] << " ";
57+
}
58+
cout << endl;
59+
}
60+
}
61+
62+
// Функция для вычисления значения определителя матрицы:
63+
float matdeterminant(float** mat, int n) {
64+
float det = 0;
65+
66+
if (n < 1) {
67+
// ОШИБКА!
68+
69+
} else if (n == 1) {
70+
// Для матрицы первого порядка значение детерминанта равно единственному элементу этой матрицы:
71+
det = mat[0][0];
72+
73+
} else if (n == 2) {
74+
// Для матрицы 2*2 определитель вычисляется как:
75+
det = mat[0][0] * mat[1][1] - mat[1][0] * mat[0][1];
76+
77+
// Для матрицы n*n определитель вычисляется разложением по строке:
78+
} else {
79+
// Выделение памяти под дополнительный минор:
80+
float** m = matalloc(n - 1, n - 1);
81+
82+
for (int j1 = 0; j1 < n; j1++) {
83+
84+
// Вычисление дополнительного минора к элементу mat[0][j1]:
85+
for (int i = 1; i < n; i++) { // начиная i с 1 вычеркиваем первую строку.
86+
int j2 = 0;
87+
for (int j = 0; j < n; j++) {
88+
if (j == j1) {
89+
// Вычеркиваем j1-й столбец:
90+
continue;
91+
}
92+
m[i - 1][j2] = mat[i][j];
93+
j2++;
94+
}
95+
}
96+
97+
// Вычисление определителя по рекурсивной формуле:
98+
det += pow(-1.0, j1 + 2.0) * mat[0][j1] * matdeterminant(m, n - 1);
99+
}
100+
101+
// Освобождение памяти выделенной под дополнительный минор.
102+
matfree(m, n - 1);
103+
}
104+
105+
return det;
106+
}
107+
108+
// Функция для получения союзной (присоединённой) квадратной матрицы:
109+
void matcofactor(float **mat, int n, float **out) {
110+
111+
// Выделение памяти под дополнительный минор:
112+
float** c = matalloc(n - 1, n - 1);
113+
114+
for (int j = 0; j < n; j++) {
115+
for (int i = 0; i < n; i++) {
116+
117+
// Получение дополнительного минора
118+
// путём вычёркивания i-й строки и j-го столбца:
119+
int i1 = 0;
120+
for (int ii = 0; ii < n; ii++) {
121+
if (ii == i)
122+
continue;
123+
int j1 = 0;
124+
for (int jj = 0; jj < n; jj++) {
125+
if (jj == j)
126+
continue;
127+
c[i1][j1] = mat[ii][jj];
128+
j1++;
129+
}
130+
i1++;
131+
}
132+
133+
float det = matdeterminant(c, n - 1); // вычисление определителя.
134+
135+
// Алгебраическое дополнение элемента mat[i][j]:
136+
out[i][j] = pow(-1.0, i + j + 2.0) * det;
137+
}
138+
}
139+
140+
// Освобождение памяти занятой под дополнительный минор:
141+
matfree(c, n - 1);
142+
}
143+
144+
// Функция для получения транспонированной квадратной матрицы:
145+
void mattranspose(float** mat, int n) {
146+
// Замена строк на столбцы:
147+
for (int i = 1; i < n; i++) {
148+
for (int j = 0; j < i; j++) {
149+
float t = mat[i][j];
150+
mat[i][j] = mat[j][i];
151+
mat[j][i] = t;
152+
}
153+
}
154+
}
155+
156+
// Функция для получения обратной квадратной матрицы
157+
// с помощью матрицы алгебраических дополнений:
158+
void matinverse(float** mat, int n, float** inverseofmat) {
159+
matcofactor(mat, n, inverseofmat); // присоединённая матрица.
160+
mattranspose(inverseofmat, n); // транспонированная присоединённая матрица.
161+
float det = matdeterminant(mat, n); // значение определителя исходной матрицы.
162+
163+
// Вычисление обратной матрицы:
164+
for (int i = 0; i < n; i++) {
165+
for (int j = 0; j < n; j++) {
166+
inverseofmat[i][j] /= det;
167+
}
168+
}
169+
}
170+
171+
// Заполение матрицы следующими элементами:
172+
// 1 2 0
173+
// -1 1 1
174+
// 1 2 3
175+
// Для отладки.
176+
void matexample1(float** mat, int n, int m) {
177+
if (n == 3 && m == 3) {
178+
mat[0][0] = 1; mat[0][1] = 2; mat[0][2] = 0;
179+
mat[1][0] = -1; mat[1][1] = 1; mat[1][2] = 1;
180+
mat[2][0] = 1; mat[2][1] = 2; mat[2][2] = 3;
181+
}
182+
}
183+
184+
int main(int argc, char** argv) {
185+
cyrillic(); // вкл. кириллицу.
186+
187+
int n, m;
188+
cout << "Введите n и m -> ";
189+
cin >> n >> m;
190+
//n = m = 3; // DEBUG.
191+
192+
if (n != m) {
193+
cout << "Для неквадратных матриц и вырожденных матриц обратных матриц не существует." << endl;
194+
195+
} else {
196+
float** srcmat = matalloc(n, m);
197+
198+
cout << "Введите элементы матрицы:" << endl;
199+
matinput(srcmat, n, m);
200+
//matexample1(srcmat, n, m); // DEBUG.
201+
202+
cout << "Вывод исходной матрицы:" << endl;
203+
matprint(srcmat, n, m);
204+
205+
float det = matdeterminant(srcmat, n);
206+
cout << "Определитель = " << det << endl;
207+
208+
if (det == 0) {
209+
cout << "Квадратная матрица обратима тогда и только тогда," << endl <<
210+
" когда она невырожденная, то есть её определитель не равен нулю." << endl;
211+
} else {
212+
// Выделение памяти под обратную матрицу:
213+
float** inverseofmat = matalloc(n, m);
214+
215+
matinverse(srcmat, n, inverseofmat);
216+
217+
cout << "Вывод обратной матрицы:" << endl;
218+
matprint(inverseofmat, n, m);
219+
220+
// Освобождение памяти под обратную матрицу:
221+
matfree(inverseofmat, n);
222+
}
223+
224+
matfree(srcmat, n);
225+
}
226+
227+
// Возврат нуля,
228+
// что означает успешное завершение программы:
229+
return EXIT_SUCCESS;
230+
}
231+

Diff for: matrix/invertible-matrix/screenshot.png

8.84 KB
Loading
91.5 KB
Binary file not shown.

0 commit comments

Comments
 (0)