JAVA小项目-计算逆矩阵

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

1.逆矩阵的定义

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

2.矩阵可逆的充要条件

<1>A的标准形为单位矩阵E.

<2>A与单位矩阵E等价.

<3>行列式不等于0/r(A)=n

3.逆矩阵的计算

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

4.问题的分解

1.输入矩阵

2.实现三种初等变换

3.生成一个n阶的单位矩阵

4.循环调用三种初等变换将原矩阵化为标准形

5.用相同的步骤将n阶单位矩阵进行转化,结果就是矩阵的逆

5.代码实现

矩阵的输入

需要注意的是不能定义为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;
    }

生成一个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;
    }

实现三种初等变换

三种初等变换

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;
            }
        }
    }

乘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;
            }
        }
    }

循环调用三种初等变换将原矩阵化为标准形

接着分解问题

1.生成对应的单位矩阵

double[][] IdentityMatrix = GetIdentityMatrix(Matrix.length);

2.调用第三种初等变换去将原矩阵先化为下三角,再化为初等矩阵

3.在变换原矩阵前,先变换生成的初等矩阵

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');
    }
}

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

写一个判断方法

    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原创,依据CC BY-SA 4.0许可证进行授权,转载请附上出处链接及本声明。
如有需要,请在留言板留言,或者添加我的QQ或者微信
我只是一个学生,如有错误或者侵权,请联系我,谢!

评论

  1. 江户川
    Android Chrome
    2 年前
    2022-12-23 18:08:37

    只怪本人没文化,一局卧槽走天下,真的c

发送评论 编辑评论


				
|´・ω・)ノ
ヾ(≧∇≦*)ゝ
(☆ω☆)
(╯‵□′)╯︵┴─┴
 ̄﹃ ̄
(/ω\)
∠( ᐛ 」∠)_
(๑•̀ㅁ•́ฅ)
→_→
୧(๑•̀⌄•́๑)૭
٩(ˊᗜˋ*)و
(ノ°ο°)ノ
(´இ皿இ`)
⌇●﹏●⌇
(ฅ´ω`ฅ)
(╯°A°)╯︵○○○
φ( ̄∇ ̄o)
ヾ(´・ ・`。)ノ"
( ง ᵒ̌皿ᵒ̌)ง⁼³₌₃
(ó﹏ò。)
Σ(っ °Д °;)っ
( ,,´・ω・)ノ"(´っω・`。)
╮(╯▽╰)╭
o(*////▽////*)q
>﹏<
( ๑´•ω•) "(ㆆᴗㆆ)
😂
😀
😅
😊
🙂
🙃
😌
😍
😘
😜
😝
😏
😒
🙄
😳
😡
😔
😫
😱
😭
💩
👻
🙌
🖕
👍
👫
👬
👭
🌚
🌝
🙈
💊
😶
🙏
🍦
🍉
😣
Source: github.com/k4yt3x/flowerhd
颜文字
Emoji
小恐龙
花!
上一篇
下一篇