目录
一、矩阵求逆的数学方法
1、伴随矩阵法
2、初等变换法
3、分块矩阵法
4、定义法
二、矩阵求逆C#代码
1、伴随矩阵法求指定3*3阶数矩阵的逆矩阵
(1)伴随矩阵数学方法
(2)代码
(3)计算
2、对任意阶数矩阵求逆
(1)计算方法
(2)代码
(3)计算
(4)计算结果
三、工程下载连接
一、矩阵求逆的数学方法
1、伴随矩阵法
2、初等变换法
3、分块矩阵法
4、定义法
二、矩阵求逆C#代码
1、伴随矩阵法求指定3*3阶数矩阵的逆矩阵
(1)伴随矩阵数学方法
(2)代码
/// <summary>
/// 计算3*3矩阵的逆矩阵
/// </summary>
/// <param name="input">输入的3*3矩阵</param>
/// <returns>计算得到的3*3逆矩阵</returns>
public static double[,] inv3(double[,] input)
{
double[,] output = new double[3, 3];
//求出伴随矩阵
output[0, 0] = input[2, 2] * input[1, 1] - input[2, 1] * input[1, 2];
output[0, 1] = input[2, 1] * input[0, 2] - input[0, 1] * input[2, 2];
output[0, 2] = input[0, 1] * input[1, 2] - input[0, 2] * input[1, 1];
output[1, 0] = input[1, 2] * input[2, 0] - input[2, 2] * input[1, 0];
output[1, 1] = input[2, 2] * input[0, 0] - input[0, 2] * input[2, 0];
output[1, 2] = input[0, 2] * input[1, 0] - input[0, 0] * input[1, 2];
output[2, 0] = input[1, 0] * input[2, 1] - input[2, 0] * input[1, 1];
output[2, 1] = input[2, 0] * input[0, 1] - input[0, 0] * input[2, 1];
output[2, 2] = input[0, 0] * input[1, 1] - input[1, 0] * input[0, 1];
//求出行列式的值
double Avalue = input[0, 0] * input[1, 1] * input[2, 2]
+ input[0, 1] * input[1, 2] * input[2, 0]
+ input[0, 2] * input[1, 0] * input[2, 1]
- input[0, 2] * input[1, 1] * input[2, 0]
- input[0, 1] * input[1, 0] * input[2, 2]
- input[0, 0] * input[1, 2] * input[2, 1];
//求出 逆矩阵
for (int i = 0; i < 3; i++)
{
for (int j = 0; j < 3; j++)
{
output[i, j] = output[i, j] / Avalue;
}
}
return output;
}
(3)计算
计算代码
计算3*3矩阵的逆矩阵
double[,] input = new double[3, 3]
{
{ 0, 1, 3 },
{ 1, -1, 0 },
{-1, 2, 1}
};
double[,] out1 = inv3(input); //方法1——只能求3*3
程序计算结果
对应数学题目
2、对任意阶数矩阵求逆
(1)计算方法
Step1
1)利用初等行变换,那么要将单位矩阵E和n阶矩阵B合并(规定为EandB_normal[ n, 2 * n])
Step2
2)将EandB_normal[ n, 2 * n]转为右半部分为上三角的矩阵
>>>这一步转换比较复杂一点,具体实现就是:
>>>第一层循环,循环变量 j 从第n列开始到第2 * n - 1列结束,目的就是将该列值都转为1,方便后边变为上三角矩阵(需要注意的是,对于第n列,应该考虑把每个值都变为1;但是到第n + 1列时,就不考虑第一个值了;第n + 2列时,不考虑第一个和第二个值;类推);
>>>第二层循环,循环变量 i 从第j - n行开始到第n - 1行结束,目的是对每一行都进行除以EandB_normal[ i, j]值的运算,这样EandB_normal[ i, j]的值就变为了1(需要注意的是,如果EandB_normal[ i, j]的值为0的话,我们考虑将该行与最后一行调换,同时循环变量 i 到第n - 2行结束;如果调换之后,EandB_normal[ i, j]的值仍然为0,那么再将该行与此时的最后一行调换,类推;但是如果一直调换,直到发现始终为0,就说明矩阵B不满秩,退出计算;如果EandB_normal[ i, j]值为负数,该行同时变号);
>>>第三层循环,循环变量 k 从第0列开始到第2 * n - 1列结束,目的是将上一步中循环到的行中的每一个值都除以EandB_normal[ i, j]的值;
>>>循环全部完成之后,矩阵EandB_normal[ n, 2 * n]就变成了右半部分为上三角的矩阵。
Step3
3)接上一步,将该矩阵转为右半部分为单位矩阵的矩阵,此时即为矩阵B的逆矩阵与单位矩阵的合并(规定为B_inverse_andE[ n, 2 * n])
>>>这一步中的循环变量是递减的,具体实现就是:
>>>第一层循环,循环变量 j 从第2 * n - 1列开始到第n列结束,目的是将该列值只保留一个1,其余变为0;
>>>第二层循环,循环变量 i 从第 j - n行开始到第0行结束;
>>>第三层循环,循环变量 k 从第0列开始到第2 * n - 1列结束;拿 j = 2 * n - 1, i = n - 1举例,此时,我们希望第n - 2行的值都加上该行最后一个值的相反数与第n - 1行乘积的对应值,第n - 3行的值都加上该行最后一个值得相反数与第n - 1行乘积的对应值,类推;(需要注意的是,j = 2 * n - 2时,i从第n - 2行开始循环,j = 2 * n - 3时,i从第n - 2行开始循环,类推);
>>>当循环全部完成之后,B_inverse_andE[ n, 2 * n]的右半部分就变为了单位矩阵,左半部分为矩阵B的逆矩阵。
Step4
4)接上一步,将B的逆矩阵取出来(规定为B_inverse[n, n])
(2)代码
/// <summary>
/// 任意矩阵求逆。(矩阵是2*2、3*3、4*4、5*5等类型)
/// </summary>
/// <param name="matrixB">输入的初始矩阵</param>
/// <param name="orderNum">矩阵行和列的数</param>
/// <returns>计算出的逆矩阵</returns>
public static double[,] MatrixInverse(double[,] matrixB, int orderNum)
{
//判断是否满秩
bool IsFullRank = true;
//n为阶级
int n = orderNum;
//####赋值####
//矩阵B
//矩阵B的逆矩阵
//单位矩阵E和矩阵B组成的矩阵
double[,] B_normal = matrixB;
double[,] B_inverse = new double[n, n];
double[,] EandB_normal = new double[n, 2 * n];
for (int i = 0; i < n; i++)
{
for (int j = 0; j < n; j++)
{
if (i == j)
EandB_normal[i, j] = 1;
else
EandB_normal[i, j] = 0;
}
for (int k = n; k < 2 * n; k++)
{
EandB_normal[i, k] = B_normal[i, k - n];
}
}
//####计算####
//中间变量数组,用于临时盛装值
double[] rowHaveZero = new double[2 * n];
//EB矩阵右边的n*n变为上三角矩阵
for (int j = n; j < 2 * n; j++)
{
int firstRowN = j - n;
int lastRowN = n;
int colCount = 2 * n;
//把EB中索引为j的列的值化为1
for (int i = firstRowN; i < lastRowN; i++)
{
//如果EBijNum值为0,就把0所在的行与此刻最后一行调换位置
//并且循环变量i的终止值减去1,直到EBijNum值不为0
//最多调换到0所在的行的下一行
double EBijNum = EandB_normal[i, j];
while (EBijNum == 0 && lastRowN > i + 1)
{
for (int k = 0; k < colCount; k++)
{
rowHaveZero[k] = EandB_normal[i, k];
EandB_normal[i, k] = EandB_normal[lastRowN - 1, k];
EandB_normal[lastRowN - 1, k] = rowHaveZero[k];
}
lastRowN -= 1;
EBijNum = EandB_normal[i, j];
}
//如果while循环是由第二个判断跳出
//即EBijNum始终为0
if (EBijNum == 0)
{
//循环变量i的终止值再减去1,然后跳出循环
lastRowN -= 1;
break;
}
//如果为负数,该行变号
if (EBijNum < 0)
{
for (int k = 0; k < colCount; k++)
{
EandB_normal[i, k] = (-1) * EandB_normal[i, k];
}
EBijNum = EandB_normal[i, j];
}
//将该值变为1,则其余值都除以EBijNum
for (int k = 0; k < colCount; k++)
{
EandB_normal[i, k] = EandB_normal[i, k] / EBijNum;
}
}
//自n列起,每列只保留一个1,呈阶梯状
int secondRowN = firstRowN + 1;
for (int i = secondRowN; i < lastRowN; i++)
{
for (int k = 0; k < colCount; k++)
{
EandB_normal[i, k] = EandB_normal[i, k]
- EandB_normal[firstRowN, k];
}
}
if (lastRowN == firstRowN)
{
//矩阵不满秩
IsFullRank = false;
break;
}
}
//不满秩,结束运算
if (!IsFullRank)
{
double[,] error = new double[n, n];
for (int i = 0; i < n; i++)
{
for (int j = 0; j < n; j++)
{
error[i, j] = 0;
}
}
//返还值均为0的矩阵
return error;
}
//将上三角矩阵变为单位矩阵
for (int j = 2 * n - 1; j > n; j--)
{
//firstRowN为参考行
//secondRowN为运算行
int firstRowN = j - n;
int secondRowN = firstRowN - 1;
int colCount = j + 1;
//从最后一列起,每列只保留一个1,其余减为0
for (int i = secondRowN; i > -1; i--)
{
double EBijNum = EandB_normal[i, j];
for (int k = 0; k < colCount; k++)
{
EandB_normal[i, k] = EandB_normal[i, k]
- EandB_normal[firstRowN, k] * EBijNum;
}
}
}
//####提取逆矩阵####
for (int i = 0; i < n; i++)
{
for (int j = 0; j < n; j++)
{
B_inverse[i, j] = EandB_normal[i, j];
}
}
return B_inverse;
}
(3)计算
private void button1_Click(object sender, EventArgs e)
{
计算3*3矩阵的逆矩阵
double[,] input = new double[3, 3]
{
{ 0, 1, 3 },
{ 1, -1, 0 },
{-1, 2, 1}
};
double[,] out1 = inv3(input); //方法1——只能求3*3
double[,] out2 = MatrixInverse(input, 3); //方法2
计算2*2矩阵的逆矩阵
double[,] input2 = new double[2, 2]
{
{ 1, 2 },
{ 3, 4 }
};
double[,] out3 = MatrixInverse(input2, 2);
//计算4*4矩阵的逆矩阵
double[,] input3 = new double[4, 4]
{
{ 2, 1,-1,2 },
{ 1, 1,1,-1 },
{0,0,2,5},
{0,0,1,3}
};
double[,] out4 = MatrixInverse(input3, 4);
}
(4)计算结果
以4*4矩阵说明
三、工程下载连接
https://download.csdn.net/download/panjinliang066333/89024543