矩阵初等变换:
1.交换矩阵的两行
2.以数K不等于0乘以矩阵某一行
3.把矩阵某一行的K倍添加到某一行上
下面通过求逆矩阵来分析矩阵初等变换:
利用初等变换求下面矩阵的逆矩阵:
2 2 1 1 0 0 1 0 0 ? ? ?
4 2 2 0 1 0 》》》 0 1 0 ? ? ?
1 4 1 0 0 1 0 0 1 ? ? ?
利用初等变换求逆矩阵的实质就是通过矩阵初等变换的三个规则,从而实现以下转变。
通过初等变换求逆矩阵的实质就是将所需矩阵变换为单位矩阵之后,与其同时变化的初始单位矩阵最后得到的结果便是改矩阵的逆矩阵,下面我们将矩阵求逆简单的划分为两部分,即“化1”,“化0”;
第一步:(0,0)化1——第0行*1/(0,0)
2 2 1 1 0 0 1 1 1/2 1/2 0 0
4 2 2 0 1 0 》》》 4 2 2 0 1 0
1 4 1 0 0 1 1 4 1 0 0 1
化“0”:1、第一行=第0行*-(1,0)+第一行
1 1 1/2 1/2 0 0 1 1 1/2 1/2 0 0
4 2 2 0 1 0 》》》 0 -2 0 -2 1 0
1 4 1 0 0 1 1 4 1 0 0 0
化“0”:2、第二行=第0行*-(2,0)+第二行
1 1 1/2 1/2 0 0 1 1 1/2 1/2 0 0
0 -2 0 -2 1 0 》》》 0 -2 0 -2 1 0
1 4 1 0 0 1 0 3 1/2 -1/2 0 1
第二步:(1,1)化“1”——第一行=第一行*1/(1,1)
1 1 1/2 1/2 0 0 1 1 1/2 1/2 0 0
0 -2 0 -2 1 0 》》》 0 1 0 1 -1/2 0
0 3 1/2 -1/2 0 1 0 3 1/2 -1/2 0 1
化“0”:(2,1)化“0”——第二行=第一行*(-(2,1))+第二行
1 1 1/2 1/2 0 0 1 1 1/2 1/2 0 0
0 1 0 1 -1/2 0 》》》 0 1 0 1 -1/2 0
0 3 1/2 -1/2 0 1 0 0 1/2 -7/2 3/2 1
第三步:(2,2)化“1”——第二行=第二行*1/(2,2)
1 1 1/2 1/2 0 0 1 1 1/2 1/2 0 0
0 1 0 1 -1/2 0 》》》 0 1 0 1 -1/2 0
0 0 1/2 -7/2 3/2 1 0 0 1 -7 3 1
化“0”:(0,1)化“0”——第0行=第一行*(-(0,1))+第0行
1 1 1/2 1/2 0 0 1 0 1/2 -1/2 1/2 0
0 1 0 1 -1/2 0 》》》 0 1 0 1 -1/2 0
0 0 1 -7/2 3/2 1 0 0 1 -7 3 1
化“0”: (0,2)化“0”——第0行=第二行*(-(0,2))+第0行
1 0 1/2 -1/2 1/2 0 1 0 0 3 -1 -1
0 1 0 1 -1/2 0 》》》 0 1 0 1 -1/2 0
0 0 1 -7 3 1 0 0 1 -7 3 1
算法实现:
/*********************************逆矩阵求解
*********************************/
CMatrix CMatrix::Inverse()const {
if (m_nRow != m_nCol) //非方阵
{
// TRACE("非方阵无法求逆!");
// throw "非方阵无法求逆!";
return (CMatrix)0;
}
CMatrix tmp(*this);
CMatrix ret(m_nRow),unit(m_nRow); //单位阵
ret.SetUnit();
unit.SetUnit();
int maxIndex;
double dMul;
for (int i = 0; i<m_nRow; i++)//执行行的次数
{
maxIndex = tmp.Pivot(i);//1.求出行中最大值的列
if (tmp.m_dData[maxIndex][i] == 0)//矩阵中某一行全为0
{
//TRACE("求逆矩阵的为非满秩矩阵,无法求逆!");
//throw "求逆矩阵的为非满秩矩阵,无法求逆!";
//return (CMatrix)-1;
return unit;
}
if (maxIndex != i) //2.如果三角阵中此列的最大值不在当前行,交换
{
tmp.Exchange(i, maxIndex);
ret.Exchange(i, maxIndex);
}
ret.Multiple(i, 1 / tmp.m_dData[i][i]);
tmp.Multiple(i, 1 / tmp.m_dData[i][i]);//3.在第i行乘以实数 (1 / tmp.m_dData[i][i])
for (int j = i + 1; j< m_nRow; j++)//4.执行当前行-1的次数
{
dMul = -tmp.m_dData[j][i];
tmp.MultipleAdd(j, i, dMul);//将第i行乘以dMul加到第j行上
ret.MultipleAdd(j, i, dMul);
}
}//end for
for (int i = m_nRow - 1; i>0; i--)//执行行-1次
{
for (int j = i - 1; j >= 0; j--)
{
dMul = -tmp.m_dData[j][i];
tmp.MultipleAdd(j, i, dMul);//将第i行乘以dMul加到第j行上
ret.MultipleAdd(j, i, dMul);
}
}//end for
return ret;
}
/********************************
*获取行中最大值的列
*********************************/
int CMatrix::Pivot(int row) const
{
int index = row;
for (int i = row + 1; i<m_nRow; i++)
{
//if (m_dData[i][row] < 0) m_dData[i][row] = -m_dData[i][row];
if (abs((long)m_dData[i][row]) > abs((long)m_dData[index][row]))
index = i;
}
return index;
}
/*****************************************************
*对调ri,rj行
******************************************************/
//对调两行ri<-->rj
CMatrix& CMatrix::Exchange(int i, int j)
{
if (i<0 || i >= m_nRow)
{
//TRACE("对换行<i>超出矩阵的行范围!");
//throw "对换行<i>超出矩阵的行范围!";
return (CMatrix)0;
}
if (j<0 || j >= m_nRow)
{
//throw "对换行<i>超出矩阵的行范围!";
//TRACE("对换行<i>超出矩阵的行范围!");
return (CMatrix)0;
}
double dTemp = 0;
for (int k = 0; k<m_nCol; k++)
{
dTemp = m_dData[i][k];
m_dData[i][k] = m_dData[j][k];
m_dData[j][k] = dTemp;
}
return *this;
}
/*******************************************************
*第index 行乘以实数mul
********************************************************/
CMatrix& CMatrix::Multiple(int index, double mul)
{
if (index <0 || index >= m_nRow)
{
//TRACE("矩阵行乘中指定的行超出矩阵行范围!");
//throw "矩阵行乘中指定的行超出矩阵行范围!";
return (CMatrix)0;
}
for (int i = 0; i<m_nCol; i++)
m_dData[index][i] *= mul;
return *this;
}
/********************************************************
*第src行乘以mul加到第index行
*********************************************************/
CMatrix& CMatrix::MultipleAdd(int index, int src, double mul)
{
if (index <0 || index >= m_nRow)
{
//TRACE("矩阵行乘相加中指定的行<index>超出矩阵行范围!");
//throw "矩阵行乘相加中指定的行<index>超出矩阵行范围!";
return (CMatrix)0;
}
if (src < 0 || src >= m_nRow)
{
// TRACE("矩阵行乘相加中指定的行<src>超出矩阵行范围!");
// throw "矩阵行乘相加中指定的行<src>超出矩阵行范围!";
return (CMatrix)0;
}
for (int j = 0; j<m_nCol; j++)
m_dData[index][j] += m_dData[src][j] * mul;
return *this;
}