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
    2022-12-23
    2022-12-23 18:08:37

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

发送评论 编辑评论


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