计算逆矩阵是矩阵计算中的一个较为重要的一个部分

1.逆矩阵的定义

A是一个n阶矩阵,若存在另一个n阶矩阵B,使得: AB=BA=E ,则称方阵A可逆,并称方阵B是A的逆矩阵

2.矩阵可逆的充要条件

  • A的标准形为单位矩阵E.
  • A与单位矩阵E等价.
  • 行列式不等于0/r(A)=n

3.逆矩阵的计算

逆矩阵有很多计算方法,我选用的是 用初等变换求矩阵的逆

4.问题的分解

  • 输入矩阵
  • 实现三种初等变换
  • 生成一个n阶的单位矩阵
  • 循环调用三种初等变换将原矩阵化为标准形
  • 用相同的步骤将n阶单位矩阵进行转化,结果就是矩阵的逆

5.代码实现

1.矩阵的输入

需要注意的是不能定义为int[][],在后续计算时,会有浮点数参与计算,int会造成问题

    public static double[][] input(){
        Scanner scanner = new Scanner(System.in);
        System.out.println("n*n矩阵的n值");
        int n = scanner.nextInt();
        double[][] arr = new double[n][n];
        for (int i = 0; i < n; i++) {
            for (int j = 0; j < n; j++) {
                arr[i][j] = scanner.nextDouble();
            }
        }
        return arr;
  
2.生成一个n阶单位矩阵

后续计算中是需要对同阶的单位矩阵进行相应的运算,需要再生成一个单位矩阵 注意这个必须返回,不然会被JVM机释放

    public static double[][] GetIdentityMatrix(int n){//得到n阶单位矩阵
        double[][] Arr = new double[n][n];
        for (int i = 0; i < n; i++) {
            for (int j = 0; j < n; j++) {
                if(i==j){
                    Arr[i][j] = 1;
                }else {
                    Arr[i][j] = 0;
                }
            }
        }
        return Arr;
    }
3.实现三种初等变换

三种初等变换

1.对调两行

2.非零常数乘某行

3.乘k加到另一行列

分别定义三个方法,进行变换即可,因为数组为引用传值,所以不必返回, 实现两行的对换,其实就是先把原数据用临时变量提取出来,对换即可,行和列需要一个字符去判断

    public static void MultiNum(double[][] Matrix,int a,double b,char RC){
        if(RC == 'r'){
            for (int i = 0; i < Matrix[a-1].length; i++) {
                Matrix[a-1][i] = Matrix[a-1][i]*b;
            }
        }else {
            for (int i = 0; i < Matrix.length; i++) {
                Matrix[i][a-1] = Matrix[i][a-1]*b;
            }
        }
    }

乘k加到另一行列,这个相对来说挺重要,后续核心基本就是在调用这个方法

    public static void MutiNumRC(double[][] Matrix,double k,int a,int b,char RC){
        if(RC == 'r'){
            for (int i = 0; i < Matrix[a-1].length; i++) {
                Matrix[a-1][i] = Matrix[a-1][i]+Matrix[b-1][i]*k;
            }
        }else {
            for (int i = 0; i < Matrix.length; i++) {
                Matrix[i][a-1] = Matrix[i][a-1]+Matrix[i][a-1]*k;
            }
        }
    }
3.循环调用三种初等变换将原矩阵化为标准形
  • 生成对应的单位矩阵
double[][] IdentityMatrix = GetIdentityMatrix(Matrix.length);
  • 调用第三种初等变换去将原矩阵先化为下三角,再化为初等矩阵
  • 在变换原矩阵前,先变换生成的初等矩阵
for (int i = 1; i <= Matrix.length; i++) {
    for (int j = i+1; j <= Matrix.length; j++) {
        System.out.println("r"+j+(-(Matrix[j-1][i-1]/Matrix[i-1][i-1]))+"r"+i);
        MutiNumRC(IdentityMatrix,-(Matrix[j-1][i-1]/Matrix[i-1][i-1]),j,i,'r');
        MutiNumRC(Matrix,-(Matrix[j-1][i-1]/Matrix[i-1][i-1]),j,i,'r');
    }
}//下三角
for (int i = Matrix.length; i >=1; i--) {
    for (int j = i-1; j>=1; j--) {
        MutiNumRC(IdentityMatrix,-(Matrix[j-1][i-1]/Matrix[i-1][i-1]),j,i,'r');
        MutiNumRC(Matrix,-(Matrix[j-1][i-1]/Matrix[i-1][i-1]),j,i,'r');
    }
}

最后要保证原矩阵变换为初等矩阵

判断如下

    public static boolean checkIdentity(double[][] Matrix){
        boolean ans = true;
        for (int i = 0; i < Matrix.length; i++) {
            for (int j = 0; j < Matrix.length; j++) {
                if (!((i == j && Matrix[i][j] == 1) || Matrix[i][j] == 0)){
                    ans = false;
                    break;
                }
            }
        }
        return ans;
    }

对变换完的原始矩阵进行判断和更正

        if(checkIdentity(Matrix)){
            return IdentityMatrix;
        }else {
            for (int i = 1; i <= Matrix.length; i++) {
                MultiNum(IdentityMatrix,i,1/Matrix[i-1][i-1],'r');
                MultiNum(Matrix,i,1/Matrix[i-1][i-1],'r');
            }
            return IdentityMatrix;
        }

该方法完整代码如下

    public static double[][] Get(double[][] Matrix){
        double[][] IdentityMatrix = GetIdentityMatrix(Matrix.length);
        for (int i = 1; i <= Matrix.length; i++) {
            for (int j = i+1; j <= Matrix.length; j++) {
                System.out.println("r"+j+(-(Matrix[j-1][i-1]/Matrix[i-1][i-1]))+"r"+i);
                MutiNumRC(IdentityMatrix,-(Matrix[j-1][i-1]/Matrix[i-1][i-1]),j,i,'r');
                MutiNumRC(Matrix,-(Matrix[j-1][i-1]/Matrix[i-1][i-1]),j,i,'r');
            }
        }//下三角
        for (int i = Matrix.length; i >=1; i--) {
            for (int j = i-1; j>=1; j--) {
                MutiNumRC(IdentityMatrix,-(Matrix[j-1][i-1]/Matrix[i-1][i-1]),j,i,'r');
                MutiNumRC(Matrix,-(Matrix[j-1][i-1]/Matrix[i-1][i-1]),j,i,'r');
            }
        }
        if(checkIdentity(Matrix)){
            return IdentityMatrix;
        }else {
            for (int i = 1; i <= Matrix.length; i++) {
                MultiNum(IdentityMatrix,i,1/Matrix[i-1][i-1],'r');
                MultiNum(Matrix,i,1/Matrix[i-1][i-1],'r');
            }
            return IdentityMatrix;
        }
    }

补充!!!

该方法对于对角线上初始有0和不可逆的矩阵会出现问题,这时需要去修改一下Get方法中的逻辑,在初始时先检测一下对角线是否有0,再写一个方法去换一下某几行即可

检查对角线是否有0

    public static boolean checkMatrix(double[][] Matrix){
        for (int i = 0; i < Matrix.length; i++) {
            for (int j = 0; j < Matrix.length; j++) {
                if(i==j&&Matrix[i][j]==0){
                    return true;
                }
            }
        }
        return false;
    }

调整如下

    public static void exchange(double[][] Matrix){
        for (int i = 0; i < Matrix.length; i++) {
            if(Matrix[i][i]==0){
                for (int j = i; j < Matrix.length; j++) {
                    if(Matrix[j][i]!=0&&Matrix[j][j]!=0){
                        ExchangeTwo(Matrix,j,i,'c');
                    }
                }
            }
        }
    }

而关于可逆不可逆,可以让它带着错误去计算,去看最后的的矩阵是否为正常矩阵, 这里选择后者。

for (int i = 0; i < Matrix.length; i++) {
    for (int j = 0; j < Matrix.length; j++) {
       if(!(Matrix[i][j]>=0||Matrix[i][j]<0)){
          System.out.println("不可逆");
          return null;
       }
    }
}

完整代码

package project_self.InverseMatrix;
 
import java.util.Scanner;
 
public class Main {
 
    /*
    三种初等变换
    1.对调两行
    2.非零常数乘某行
    3.乘k加到另一行列
     */
 
    public static void ExchangeTwo(double[][] Matrix, int a,int b,char RC){
        double[] temp = new double[Matrix[a-1].length];
        if(RC == 'r'){
            for (int i = 0; i < Matrix[a-1].length; i++) {
                temp[i] = Matrix[a-1][i];
                Matrix[a-1][i] = Matrix[b-1][i];
                Matrix[b -1][i] = temp[i];
            }
        }else {
            for (int i = 0; i < Matrix.length; i++) {
                temp[i] = Matrix[i][a-1];
                Matrix[i][a-1] = Matrix[i][b-1];
                Matrix[i][b-1] = temp[i];
            }
        }
    }
 
    public static void MultiNum(double[][] Matrix,int a,double b,char RC){
        if(RC == 'r'){
            for (int i = 0; i < Matrix[a-1].length; i++) {
                Matrix[a-1][i] = Matrix[a-1][i]*b;
            }
        }else {
            for (int i = 0; i < Matrix.length; i++) {
                Matrix[i][a-1] = Matrix[i][a-1]*b;
            }
        }
    }
 
    public static void MutiNumRC(double[][] Matrix,double k,int a,int b,char RC){
        if(RC == 'r'){
            for (int i = 0; i < Matrix[a-1].length; i++) {
                Matrix[a-1][i] = Matrix[a-1][i]+Matrix[b-1][i]*k;
            }
        }else {
            for (int i = 0; i < Matrix.length; i++) {
                Matrix[i][a-1] = Matrix[i][a-1]+Matrix[i][a-1]*k;
            }
        }
    }
 
    public static double[][] Get(double[][] Matrix){
        double[][] IdentityMatrix = GetIdentityMatrix(Matrix.length);
        if(checkMatrix(Matrix)){
            exchange(Matrix);
        }
        for (int i = 1; i <= Matrix.length; i++) {
            for (int j = i+1; j <= Matrix.length; j++) {
                System.out.println("r"+j+(-(Matrix[j-1][i-1]/Matrix[i-1][i-1]))+"r"+i);
                MutiNumRC(IdentityMatrix,-(Matrix[j-1][i-1]/Matrix[i-1][i-1]),j,i,'r');
                MutiNumRC(Matrix,-(Matrix[j-1][i-1]/Matrix[i-1][i-1]),j,i,'r');
            }
        }//下三角
        for (int i = Matrix.length; i >=1; i--) {
            for (int j = i-1; j>=1; j--) {
                MutiNumRC(IdentityMatrix,-(Matrix[j-1][i-1]/Matrix[i-1][i-1]),j,i,'r');
                MutiNumRC(Matrix,-(Matrix[j-1][i-1]/Matrix[i-1][i-1]),j,i,'r');
            }
        }
        for (double[] matrix : Matrix) {
            for (int j = 0; j < Matrix.length; j++) {
                if (!(matrix[j] >= 0 || matrix[j] < 0)) {
                    System.out.println("不可逆");
                    return null;
                }
            }
        }
        if(checkIdentity(Matrix)){
            return IdentityMatrix;
        }else {
            for (int i = 1; i <= Matrix.length; i++) {
                MultiNum(IdentityMatrix,i,1/Matrix[i-1][i-1],'r');
                MultiNum(Matrix,i,1/Matrix[i-1][i-1],'r');
            }
            return IdentityMatrix;
        }
    }
 
    public static boolean checkIdentity(double[][] Matrix){
        boolean ans = true;
        for (int i = 0; i < Matrix.length; i++) {
            for (int j = 0; j < Matrix.length; j++) {
                if (!((i == j && Matrix[i][j] == 1) || Matrix[i][j] == 0)){
                    ans = false;
                    break;
                }
            }
        }
        return ans;
    }
 
    public static double[][] GetIdentityMatrix(int n){//得到n阶单位矩阵
        double[][] Arr = new double[n][n];
        for (int i = 0; i < n; i++) {
            for (int j = 0; j < n; j++) {
                if(i==j){
                    Arr[i][j] = 1;
                }else {
                    Arr[i][j] = 0;
                }
            }
        }
        return Arr;
    }
 
    public static double[][] input(){
        Scanner scanner = new Scanner(System.in);
        System.out.println("n*n矩阵的n值");
        int n = scanner.nextInt();
        double[][] arr = new double[n][n];
        for (int i = 0; i < n; i++) {
            for (int j = 0; j < n; j++) {
                arr[i][j] = scanner.nextDouble();
            }
        }
        return arr;
    }
 
    public static void printArr(double[][] arr){
        for (double[] ints : arr) {
            for (int j = 0; j < arr.length; j++) {
                System.out.printf("%.2f\t",ints[j]);
            }
            System.out.println();
        }
    }
 
    public static boolean checkMatrix(double[][] Matrix){
        for (int i = 0; i < Matrix.length; i++) {
            for (int j = 0; j < Matrix.length; j++) {
                if(i==j&&Matrix[i][j]==0){
                    return true;
                }
            }
        }
        return false;
    }
 
    public static void exchange(double[][] Matrix){
        for (int i = 0; i < Matrix.length; i++) {
            if(Matrix[i][i]==0){
                for (int j = i; j < Matrix.length; j++) {
                    if(Matrix[j][i]!=0&&Matrix[j][j]!=0){
                        ExchangeTwo(Matrix,j,i,'c');
                    }
                }
            }
        }
    }
 
    public static void main(String[] args) {
        double[][] Matrix = input();
        double[][] ans = Get(Matrix);
        if(ans!=null){
            printArr(ans);
        }else {
            System.out.println("结束了");
        }
    }
}

最后,此篇文章转自于室友栋dong的博客,一起学习数学被"虐",转载此篇文章也得到了他的同意,故在此重申说明一下。

最后修改:2023 年 02 月 03 日
如果觉得我的文章对你有用,请随意赞赏