C++ Rookiss Part2 게임 수학과 DirectX12 : Matrix
🙇♀️Matrix
🪐Matrix
$M * N$ 행렬은 M개의 행과 N개의 열로 이루어진 실수들의 정사각 배열이다. 행과 열로 이루어지고 구성하는 수들을 성분 또는 원소라고 부른다.
- 행렬 곱셈
$M * N$ 행렬 $A$, $N * P$ 행렬 $B$가 있으면 둘의 곱 $AB$가 정의된다. 곱 $AB$는 하나의 $M * P$ 행렬이다.
$C_{ij} = A_{i}* * B*_{j}$
$A = \begin{bmatrix}-1&5&-4\ 3&2&1 \end{bmatrix}$
$B = \begin{bmatrix}2&1&0\ 0&-2&1 \ -1&2&3 \end{bmatrix}$
$AB = \begin{bmatrix}(-1,5,-4)(2,0,-1)&(-1,5,-4)(1,-2,2)&(-1,5,-4)(0,1,3)\ (3,2,1)(2,0,-1)&(3,2,1)(1,-2,2)&(3,2,1)(0,1,3) \end{bmatrix} \ = \begin{bmatrix}2&-19&7\ 5&1&5 \end{bmatrix}$
- 벡터와 행렬의 곱셉
$uA = xA1* + yA2* + z A3* …$
- 전치행렬
$M * N$ 행렬의 전치는 $N * M$이다. 행렬 $M$의 전치행렬을 $M^T$로 표기한다.
- 단위행렬
- 정사각형의 행렬 : 정방행렬
- 정방행렬에서 좌상에서 우하로의 주된 대각선에 있는 성분들 : 주대각
- 주대각 성분들만 1이고 나머지는 모두 0인 정방행렬 : 단위행렬
$A = M * N, B = N * P, I = N * N이면 AI = A 이고 IB = B$
M이 정방행렬일 때 단위행렬과의 곱셈은 교환법칙 만족
$MI = IM = M$
- 행렬식
행렬식 : 정방행렬을 입력받아서 실숫값을 출력하는 특별한 함수
$정방행렬 A의 행렬식 = det A$
$A = \begin{bmatrix}A11&A12&A13\ A21&A22&A23 \ A31&A32&A33 \end{bmatrix}$
$소행렬A11 = \begin{bmatrix}A22&A23\ A32&A33 \end{bmatrix}$
$소행렬A22 = \begin{bmatrix}A11&A13\ A31&A33 \end{bmatrix}$
$소행렬A13 = \begin{bmatrix}A21&A22\ A31&A32 \end{bmatrix}$
행렬식
- 딸림행렬
A가 $N * N$ 행렬이라고 할 때, $C_{ij} = (-1)^(i+j) det소행렬A_{ij}$를 $A_{ij}$의 여인수라고 부른다.
각 성분의 $C_{ij}$를 계산해서 $ij$번째 위치에 배치한 $C_{A}$행렬을 행렬$A$의 여인수행렬이라고 부른다.
$C_{A}$의 전치행렬을 $A$의 딸림행렬이라고 부르고
$A* = C_{A}^T$로 표현한다.
- 역행렬
$A^{-1} = A* / det A$
역행렬 = 딸림행렬 / 행렬식
- 전치 행렬 함수 만들기
#include <iostream>
using namespace std;
#include <vector>
//vector<vector<int>> matrix;
vector<vector<int>> CreateMatrix(int m, int n)
{
vector<vector<int>> matrix/*(m, vector<int>(n))*/;
vector<int> arr;
int input;
for (int i = 0; i < m; i++)
{
for (int j = 0; j < n; j++)
{
cin >> input;
arr.push_back(input);
}
matrix.push_back(arr);
arr.clear();
}
return matrix;
}
void PrintMatrix(vector<vector<int>> matrix)
{
for (int i = 0; i < matrix.size(); i++)
{
for (int j = 0; j < matrix[0].size(); j++)
cout << matrix[i][j] << " ";
cout << endl;
}
}
vector<vector<int>> CreateTransposition(vector<vector<int>> matrix) // 전치 행렬 만들기
{
vector<vector<int>> TransMatrix;
vector<int> arr;
for (int i = 0; i < matrix[0].size(); i++) // 열의 수
{
for (int j = 0; j < matrix.size(); j++) // 행의 수
{
arr.push_back(matrix[j][i]);
}
TransMatrix.push_back(arr);
arr.clear();
}
return TransMatrix;
}
int main()
{
int m, n;
cout << "M x N행렬을 만들기 위한 M과 N을 입력하세요 " << endl;
cout << "M :";
cin >> m;
cout << "N :";
cin >> n;
auto matrix = CreateMatrix(m, n);
PrintMatrix(matrix);
auto transMatrix = CreateTransposition(matrix);
PrintMatrix(transMatrix);
}
- 행렬식과 역행렬 함수 포함 프로그램
#include <iostream>
using namespace std;
#include <vector>
//vector<vector<int>> matrix;
vector<vector<double>> CreateMatrix(int m, int n)
{
vector<vector<double>> matrix/*(m, vector<int>(n))*/;
vector<double> arr;
int input;
for (int i = 0; i < m; i++)
{
for (int j = 0; j < n; j++)
{
cin >> input;
arr.push_back(input);
}
matrix.push_back(arr);
arr.clear();
}
return matrix;
}
void PrintMatrix(vector<vector<double>> matrix)
{
for (int i = 0; i < matrix.size(); i++)
{
for (int j = 0; j < matrix[0].size(); j++)
cout << round(matrix[i][j] * 100 + 0.5) / 100 << " ";
cout << endl;
}
}
vector<vector<double>> CreateTransposition(vector<vector<double>> matrix)
{
vector<vector<double>> TransMatrix;
vector<double> arr;
for (int i = 0; i < matrix[0].size(); i++) // 열의 수
{
for (int j = 0; j < matrix.size(); j++) // 행의 수
{
arr.push_back(matrix[j][i]);
}
TransMatrix.push_back(arr);
arr.clear();
}
return TransMatrix;
}
vector<vector<double>> littleMatrix(vector<vector<double>> matrix, int line, int row)
{
vector<vector<double>> ret;
vector<double> arr;
for (int i = 0; i < matrix.size(); i++)
{
for (int j = 0; j < matrix[0].size(); j++)
{
if (i == line || j == row)
continue;
arr.push_back(matrix[i][j]);
}
if (arr.size() == 0)
continue;
ret.push_back(arr);
arr.clear();
}
return ret;
}
double determinant2By2(vector<vector<double>> matrix)
{
return (matrix[0][0] * matrix[1][1] - matrix[0][1] * matrix[1][0]);
}
double determinant3By3(vector<vector<double>> matrix)
{
double ret =
matrix[0][0] * determinant2By2(littleMatrix(matrix, 0, 0))
- matrix[0][1] * determinant2By2(littleMatrix(matrix, 0, 1))
+ matrix[0][2] * determinant2By2(littleMatrix(matrix, 0, 2));
return ret;
}
double determinant4By4(vector<vector<double>> matrix)
{
double ret =
matrix[0][0] * determinant3By3(littleMatrix(matrix, 0, 0))
- matrix[0][1] * determinant3By3(littleMatrix(matrix, 0, 1))
+ matrix[0][2] * determinant3By3(littleMatrix(matrix, 0, 2))
- matrix[0][3] * determinant3By3(littleMatrix(matrix, 0, 3));
return ret;
}
vector<vector<double>> InverseMatrix(vector<vector<double>> matrix)
{
vector<vector<double>> invMat;
vector<double> arr;
for (int i = 0; i < matrix.size(); i++)
{
for (int j = 0; j < matrix[0].size(); j++)
{
if((i + j) % 2 == 0)
arr.push_back(determinant3By3(littleMatrix(matrix, i, j)));
else
arr.push_back(-determinant3By3(littleMatrix(matrix, i, j)));
}
if (arr.size() == 0)
continue;
invMat.push_back(arr);
arr.clear();
}
auto temp = CreateTransposition(invMat);
invMat.clear();
int det4 = determinant4By4(matrix);
for (int i = 0; i < matrix.size(); i++)
{
for (int j = 0; j < matrix[0].size(); j++)
{
arr.push_back(temp[i][j] / det4);
}
if (arr.size() == 0)
continue;
invMat.push_back(arr);
arr.clear();
}
return invMat;
}
int main()
{
/*int m, n;
cout << "M x N행렬을 만들기 위한 M과 N을 입력하세요 " << endl;
cout << "M :";
cin >> m;
cout << "N :";
cin >> n;
auto matrix = CreateMatrix(m, n);
PrintMatrix(matrix);
auto transMatrix = CreateTransposition(matrix);
PrintMatrix(transMatrix);*/
vector < vector<double>> matrix4By4 =
{
{1, 2, 3, 4},
{5, 8, 7, 8},
{9, 10, 9, 12},
{13, 14, 15, 16}
};
auto lMat = littleMatrix(matrix4By4, 0, 1);
//PrintMatrix(lMat);
double det4 = determinant4By4(matrix4By4);
cout << det4 << endl;;
auto mat4 = InverseMatrix(matrix4By4);
PrintMatrix(mat4);
}