[C++基础] Matrix类的实现(三)求行列式的值
作者:互联网
定义与解法
**定义:**n阶行列式等于所有取自不同行不同列的n个元素的乘积的代数和。
解法:
- 定义法:根据定义n阶行列式的值计算公式如下:
∣ a 11 a 12 . . . a 1 n a 21 a 22 . . . a 2 n . . . . . . . . . . . . a n 1 a n 2 . . . a n n ∣ = ∑ j 1 j 2 . . . j n ( − 1 ) τ ( j 1 j 2 . . . j n ) a 1 j 1 a 2 j 2 . . . a n j n \begin{vmatrix} a_{11}& a_{12} & ... & a_{1n} \\ a_{21}& a_{22} & ... & a_{2n} \\ ...& ... & ... & ... \\ a_{n1}& a_{n2}^{} & ... & a_{nn} \end{vmatrix} =\sum_{ j_{1}j_{2}...j_{n}}^{} (-1)^{\tau(j_{1}j_{2}...j_{n}) }a_{1j_{1}}a_{2j_{2}}...a_{nj_{n}} ∣∣∣∣∣∣∣∣a11a21...an1a12a22...an2............a1na2n...ann∣∣∣∣∣∣∣∣=j1j2...jn∑(−1)τ(j1j2...jn)a1j1a2j2...anjn
其中 τ ( j 1 j 2 . . . j n ) \tau(j_{1}j_{2}...j_{n}) τ(j1j2...jn)为 j 1 j 2 . . . j n j_{1}j_{2}...j_{n} j1j2...jn目前排列的逆序数。如果读者还对逆序数不清楚,可以百度一下,本文不做阐述。
由于要对 j 1 j 2 . . . j n j_{1}j_{2}...j_{n} j1j2...jn所有排列进行计算,总共有 j 1 j 2 . . . j n j_{1}j_{2}...j_{n} j1j2...jn有 n ! n! n!项。 - 降阶法(展开法)
降阶法我们需要用到代数余子式,因此在计算之前,先了解一下代数余子式
代数余子式定义:
∣ a 11 a 12 . . . a 1 n a 21 a 22 . . . a 2 n . . . . . . . . . . . . a n 1 a n 2 . . . a n n ∣ \begin{vmatrix} a_{11}& a_{12} & ... & a_{1n} \\ a_{21}& a_{22} & ... & a_{2n} \\ ...& ... & ... & ... \\ a_{n1}& a_{n2}^{} & ... & a_{nn} \end{vmatrix} ∣∣∣∣∣∣∣∣a11a21...an1a12a22...an2............a1na2n...ann∣∣∣∣∣∣∣∣
在上面行列式中划去元素 a i j a_{ij} aij所在的第 i i i行第 j j j列,剩下的 ( n − 1 ) 2 {(n-1)}^{2} (n−1)2个元素按原来的排法构成一个 n − 1 n-1 n−1阶的行列式 M i j M_{ij} Mij,称 M i j M_{ij} Mij为元素 a i j a_{ij} aij的余子式,Aij=(-1)i+j Mij A i j = ( n − 1 ) i + j M i j A_{ij}={(n-1)}^{i+j}M_{ij} Aij=(n−1)i+jMij称为元素的代数余子式。(如不能理解,建议草稿本上画一画)
则行列式的值可以表示为(按第 i i i行展开) D = a i 1 A i 1 + a i 2 A i 2 + . . . + a i n A i n D=a_{i1}A_{i1}+a_{i2}A_{i2}+...+a_{in}A_{in} D=ai1Ai1+ai2Ai2+...+ainAin
对于每一个 A i k A_{ik} Aik可以对其在进行展开。 - 变换法
利用行列式中的某一行(列)的每一个数对应的加到某一行(列)上去,行列式值不变的性质,我们将行列式变为上三角或者下三角形,然后直接将对角线上的值进行相乘即可,如下图:
∣ 1 2 3 3 5 6 2 9 2 ∣ → ∣ 1 2 3 0 − 1 − 3 0 5 − 10 ∣ → ∣ 1 2 3 0 − 1 − 3 0 0 − 25 ∣ \begin{vmatrix} 1 & 2 & 3 \\ 3 & 5 & 6 \\ 2 & 9& 2 \end{vmatrix} \rightarrow \begin{vmatrix} 1 & 2 & 3 \\ 0 & -1 & -3 \\ 0 & 5 & -10 \end{vmatrix} \rightarrow \begin{vmatrix} 1 & 2 & 3 \\ 0 & -1 & -3 \\ 0 & 0 & -25 \end{vmatrix} ∣∣∣∣∣∣132259362∣∣∣∣∣∣→∣∣∣∣∣∣1002−153−3−10∣∣∣∣∣∣→∣∣∣∣∣∣1002−103−3−25∣∣∣∣∣∣
上述行列式的值就是 1 ∗ ( − 1 ) ∗ ( − 25 ) = 25 1*(-1)*(-25)=25 1∗(−1)∗(−25)=25
算法
本文求行列式的值的算法采用了将上述解法中(2)和(3)的结合,算法过程如下:
- 先对该矩阵进行判断是否可以进行行列式计算,不可则不执行,可以就执行下面步骤
- 从 a 11 a_{11} a11开始,找到第一列不为 0 0 0的项 a i 1 a_{i1} ai1,以 a i 1 a_{i1} ai1为基准,对同一列的项所在的行进行对应的加加减减,最终目的是使得该行列式的第一列除了 a i 1 a_{i1} ai1,其余项都为0
- 如果第2步发现第一列全是0,则该行列式值为0
- 按第一列展开,因为只有
a
i
1
≠
0
a_{i1}≠0
ai1=0,所以行列式值
D
n
=
(
−
1
)
i
+
1
a
i
1
A
i
1
D_{n}={(-1)}^{i+1}a_{i1}A_{i1}
Dn=(−1)i+1ai1Ai1
于是又以$A_{i1}为新的行列式,从2开始进行计算 - 如果行列式只有二阶了,退出循环并计算该二阶行列式的值 D 2 = a 11 ∗ a 22 − a 12 ∗ a 21 D_{2}=a_{11}*a_{22}-a_{12}*a_{21} D2=a11∗a22−a12∗a21,最后融合到已经有结果的 D n D_{n} Dn中去。
代码
if (rowCount != columnCount) return -2147483648.0;
if (rowCount == 1) return GetItem(0, 0);
if (rowCount == 2) return GetItem(0, 0) * GetItem(1, 1) - GetItem(0, 1) * GetItem(1, 0);
Matrix temp(rowCount,columnCount);
double res = 1.0;
for (int i = 0; i < rowCount; i++)
{
for (int j = 0; j < columnCount; j++)
{
temp.SetItem(i, j, r[i][j]);
}
}
while (true)
{
if (temp.GetRowCount() == 2) {
res *= (temp.GetItem(0, 0) * temp.GetItem(1, 1) - temp.GetItem(0, 1) * temp.GetItem(1, 0));
break;
}
//找到第一列第一个不为0的数,这个数不变
int row = 0;
while (row < temp.GetRowCount() && temp.GetItem(row, 0) == 0) row++;
if (row == temp.GetRowCount()) { res *= 0; break; }
//计算到结果中去
res *= temp.GetItem(row, 0);
res *= (row % 2 == 0 ? 1 : -1);
//把该列除了选中的这个数全部置0
for (int i = 0; i < temp.GetRowCount(); i++)
{
if(i == row || temp.GetItem(i, 0) == 0) continue;
double coefficience = temp.GetItem(i, 0) / temp.GetItem(row, 0);
for (int j = 1; j < columnCount; j++)
{
double val = temp.GetItem(i, j) - coefficience * temp.GetItem(row, j);
temp.SetItem(i, j, val);
}
temp.SetItem(i, 0, 0);
}
Matrix p(temp.GetRowCount() - 1, temp.GetRowCount() - 1);
for (int i = 0; i < p.GetRowCount(); i++)
{
for (int j = 0; j < p.GetColumnCount(); j++)
{
p.SetItem(i, j, temp.GetItem(i + 1, j + 1));
}
}
temp.Reshape(p);
}
return res;
作者源码
https://github.com/PureZhao/BaseMathLib
项目里面找两个文件:
Matrix.h
Matrix.cpp
标签:...,Matrix,temp,C++,vmatrix,行列式,GetItem,row 来源: https://blog.csdn.net/weixin_40885067/article/details/112465241