Time : 2020.02.05-2020.02.10
记录c++矩阵求逆的三种方法。
方法1:
#include <iostream>
#include <stdio.h>
#include <cstdio>
#include<vector>
#include <string>
#include <cmath>
#include "opencv2/highgui/highgui.hpp"
using namespace std;
int matrixInversion(vector<vector<double>> &a, int n)
{
int *is = new int[n];
int *js = new int[n];
int i,j,k;
double d,p;
for ( k = 0; k < n; k++)
{
d = 0.0;
for (i=k; i<=n-1; i++)
for (j=k; j<=n-1; j++)
{
p=fabs(a[i][j]);
if (p>d) { d=p; is[k]=i; js[k]=j;}
}
if ( 0.0 == d )
{
free(is); free(js); printf("err**not inv\n");
return(0);
}
if (is[k]!=k)
for (j=0; j<=n-1; j++)
{
p=a[k][j];
a[k][j]=a[is[k]][j];
a[is[k]][j]=p;
}
if (js[k]!=k)
for (i=0; i<=n-1; i++)
{
p=a[i][k];
a[i][k]=a[i][js[k]];
a[i][js[k]]=p;
}
a[k][k] = 1.0/a[k][k];
for (j=0; j<=n-1; j++)
if (j!=k)
{
a[k][j] *= a[k][k];
}
for (i=0; i<=n-1; i++)
if (i!=k)
for (j=0; j<=n-1; j++)
if (j!=k)
{
a[i][j] -= a[i][k]*a[k][j];
}
for (i=0; i<=n-1; i++)
if (i!=k)
{
a[i][k] = -a[i][k]*a[k][k];
}
}
for ( k = n-1; k >= 0; k--)
{
if (js[k]!=k)
for (j=0; j<=n-1; j++)
{
p = a[k][j];
a[k][j] = a[js[k]][j];
a[js[k]][j]=p;
}
if (is[k]!=k)
for (i=0; i<=n-1; i++)
{
p = a[i][k];
a[i][k]=a[i][is[k]];
a[i][is[k]] = p;
}
}
free(is); free(js);
return(1);
}
int main()
{
//prior_testMatrix(); // 这个是测试原来的方法的函数,内容和原来的main函数一致
int i,j;
static vector<vector<double>> a(4,vector<double>(4));
a={{0.2368,0.2471,0.2568,1.2671},
{1.1161,0.1254,0.1397,0.1490},
{0.1582,1.1675,0.1768,0.1871},
{0.1968,0.2071,1.2168,0.2271}};
static vector<vector<double>> b(4,vector<double>(4)); // 拷贝a
for (i=0; i< 4; i++){
for (j=0; j< 4; j++){
b[i][j]=a[i][j];
}// 拷贝a
}
cout << (i=matrixInversion(b,4)) << endl; // 计算逆矩阵,结果在b中
if (i!=0){
cout<<"矩阵A"<<endl;
for (i=0; i<=3; i++){
for (j=0; j<4; j++)
cout<<a[i][j]<<endl;
}
cout<<"矩阵A的逆矩阵"<<endl;
for (i=0; i<4; i++){
for (j=0; j<=3; j++)
cout<<b[i][j]<<endl;
}
}
}
方法2:伴随矩阵求逆(耗时)
#include <iostream>
#include <stdio.h>
#include <cstdio>
#include<vector>
#include <string>
#include <cmath>
#include "opencv2/highgui/highgui.hpp"
#define N 3 //测试矩阵维数定义
using namespace std;
//按第一行展开计算|A|
double getA(vector<vector<double> > &arcs,int n)
{
if(n==1){
return arcs[0][0];
}
double ans = 0;
vector<vector<double> > temp(N,vector<double>(N));
temp={{0,0,0},{0,0,0},{0,0,0}};
int i,j,k;
for(i=0;i<n;i++){
for(j=0;j<n-1;j++){
for(k=0;k<n-1;k++){
temp[j][k] = arcs[j+1][(k>=i)?k+1:k];
}
}
double t = getA(temp,n-1);
if(i%2==0){
ans += arcs[0][i]*t;
}
else{
ans -= arcs[0][i]*t;
}
}
return ans;
}
//计算每一行每一列的每个元素所对应的余子式,组成A*
void getAStart(vector<vector<double> > &arcs,int n,vector<vector<double> > &ans)
{
if(n==1){
ans[0][0] = 1;
return;
}
int i,j,k,t;
vector<vector<double> > temp(N,vector<double>(N));
temp={{0,0,0},{0,0,0},{0,0,0}};
for(i=0;i<n;i++){
for(j=0;j<n;j++){
for(k=0;k<n-1;k++){
for(t=0;t<n-1;t++){
temp[k][t] = arcs[k>=i?k+1:k][t>=j?t+1:t];
}
}
ans[j][i] = getA(temp,n-1);
//此处顺便进行了转置
if((i+j)%2 == 1){
ans[j][i] = - ans[j][i];
}
}
}
}
//得到给定矩阵src的逆矩阵保存到des中。
bool GetMatrixInverse(vector<vector<double> > &src,int n,vector<vector<double> > &des)
{
double flag=getA(src,n);
cout<<"flag "<<flag<<endl;
vector<vector<double> > t(N,vector<double>(N));
t={{0,0,0},{0,0,0},{0,0,0}};
if(0==flag){
cout<< "原矩阵行列式为0,无法求逆。请重新运行" <<endl;
return false;//如果算出矩阵的行列式为0,则不往下进行
}
else{
getAStart(src,n,t);
for(int i=0;i<n;i++){
for(int j=0;j<n;j++){
des[i][j]=t[i][j]/flag;
}
}
}
return true;
}
int main()
{
bool flag;//标志位,如果行列式为0,则结束程序
vector<vector<double> > matrix_before(N,vector<double>(N));
//随机数据,可替换
srand((unsigned)time(0));
for(int i=0; i<N ;i++)
{
for(int j=0; j<N;j++)
{
matrix_before[i][j]=rand()%100 *0.01;
}
}
cout<<"原矩阵:"<<endl;
for(int i=0; i<N ;i++){
for(int j=0; j<N;j++){
cout <<matrix_before[i][j]<<" ";
}
cout<<endl;
}
vector<vector<double> > matrix_after(N,vector<double>(N));
flag=GetMatrixInverse(matrix_before,N,matrix_after);
if(false==flag)
return 0;
cout<<"逆矩阵:"<<endl;
for(int i=0; i<N ;i++){
for(int j=0; j<N;j++){
cout <<matrix_after[i][j] <<" ";
//cout << *(*(matrix_after+i)+j)<<" ";
}
cout<<endl;
}
GetMatrixInverse(matrix_after,N,matrix_before);
cout<<"反算的原矩阵:"<<endl;//为了验证程序的精度
for(int i=0; i<N ;i++){
for(int j=0; j<N;j++){
cout << matrix_before[i][j]<<" ";
}
cout<<endl;
}
return 0;
}
将其整理为类实现:
#include <iostream>
#include <stdio.h>
#include <cstdio>
#include <vector>
#include <string>
#include "opencv2/highgui/highgui.hpp"
#define N 3 //测试矩阵维数定义
using namespace std;
class Inv{
public:
Inv(){};//构造函数
~Inv(){};//析构函数
double getA(vector<vector<double>> &arcs,int n);
void getAStart(vector<vector<double>> &arcs,int n,vector<vector<double>> &ans);
bool GetMatrixInverse(vector<vector<double>> &src,int n,vector<vector<double>> &des);
};
int main(void)
{
bool flag;//标志位,如果行列式为0,则结束程序
vector<vector<double>> matrix_before(3,vector<double>(3));
matrix_before={{1,0,0},{0,1,0},{0,0,1}};
vector<vector<double> > matrix_after(N,vector<double>(N));
Inv I;
flag=I.GetMatrixInverse(matrix_before,N,matrix_after);
if(false==flag)
return 0;
cout<<"逆矩阵:"<<endl;
for(int i=0; i<N ;i++){
for(int j=0; j<N;j++){
cout <<matrix_after[i][j] <<" ";
}
cout<<endl;
}
/*cout<<"反算的原矩阵:"<<endl;//为了验证程序的精度
for(int i=0; i<N ;i++){
for(int j=0; j<N;j++){
cout << matrix_before[i][j]<<" ";
}
cout<<endl;
}*/
return 0;
}
//按第一行展开计算|A|
double Inv::getA(vector<vector<double>> &arcs,int n)
{
if(n==1){
return arcs[0][0];
}
double ans = 0;
vector<vector<double>> temp(N,vector<double>(N));
temp={{0,0,0},{0,0,0},{0,0,0}};
int i,j,k;
for(i=0;i<n;i++){
for(j=0;j<n-1;j++){
for(k=0;k<n-1;k++){
temp[j][k] = arcs[j+1][(k>=i)?k+1:k];
}
}
double t = getA(temp,n-1);
if(i%2==0){
ans += arcs[0][i]*t;
}
else{
ans -= arcs[0][i]*t;
}
}
return ans;
}
//计算每一行每一列的每个元素所对应的余子式,组成A*
void Inv::getAStart(vector<vector<double>> &arcs,int n,vector<vector<double>> &ans)
{
if(n==1){
ans[0][0] = 1;
return;
}
int i,j,k,t;
vector<vector<double>> temp(N,vector<double>(N));
temp={{0,0,0},{0,0,0},{0,0,0}};
for(i=0;i<n;i++){
for(j=0;j<n;j++){
for(k=0;k<n-1;k++){
for(t=0;t<n-1;t++){
temp[k][t] = arcs[k>=i?k+1:k][t>=j?t+1:t];
}
}
ans[j][i] = getA(temp,n-1);
//此处顺便进行了转置
if((i+j)%2 == 1){
ans[j][i] = - ans[j][i];
}
}
}
}
//得到给定矩阵src的逆矩阵保存到des中。
bool Inv::GetMatrixInverse(vector<vector<double>> &src,int n,vector<vector<double>> &des)
{
double flag=getA(src,n);
cout<<"flag "<<flag<<endl;
vector<vector<double>> t(N,vector<double>(N));
t={{0,0,0},{0,0,0},{0,0,0}};
if(0==flag){
cout<< "原矩阵行列式为0,无法求逆。请重新运行" <<endl;
return false;//如果算出矩阵的行列式为0,则不往下进行
}
else{
getAStart(src,n,t);
for(int i=0;i<n;i++){
for(int j=0;j<n;j++){
des[i][j]=t[i][j]/flag;
}
}
}
return true;
}
方法3:高斯-约旦消元法求逆
#include<iostream>
#include<iomanip>
using namespace std;
//左下角变换0 若对角不为1元素下方元素为1交换两行
//对角变1
//右上角变换0
void LD_triangle(float temp[6][12],int n);
void RU_triangle(float temp[6][12],int n);
void Aii_Cto_1(float temp[6][12],int n);
void Display(float A[6][12],int m,int n);
int Find(float temp[6][12],int i,int n);
void Swap(float temp[6][12],int i,int j,int n);
class Matrix{
public:
Matrix(){
n=9;
for(int i=0;i<6;i++)
for(int j=0;j<12;j++)
A[i][j]=0;//初始化矩阵A 6*12 存放的是目标矩阵|单位矩阵
Det_A=0;
}
void Conversion();
void Input();
bool Cal_DetA();
friend void Save_To_Result(float temp[6][12],Matrix &D);
void Cheak_IsSolvable();
void Out_Result();
private:
int n; //阶
float A[6][12]; //矩阵
float result[6][6]; //逆矩阵结果
float Det_A; //|A|值:是否存在逆矩阵
};
int main(){
cout<<"\n\t\t-------求逆矩阵(初等变换法)-------"<<endl<<endl;
while(1){
Matrix D;
D.Input();
D.Cheak_IsSolvable(); //可解
D.Conversion(); //变换
D.Out_Result(); //输出
}
return 1;
}
//输入要处理的矩阵以及单位矩阵,可更改输入方式
void Matrix::Input(){
cout<<"\n---行列数:";
cin>>n;
cout<<endl<<"输入行列式:"<<endl;
for(int i=0;i<n;i++)
for(int j=0;j<n;j++)
cin>>A[i][j];
int j=0;
for(int i=n;i<2*n;i++){
A[j][i]=1;
j++;
}
}
//检验是否可解
void Matrix::Cheak_IsSolvable(){
while(1){
if(Cal_DetA()){
cout<<"\n|A|="<<Det_A<<endl<<endl;
cout<<"(A|E)="<<endl;
Display(A,n,2*n);
break;
}
else{
cout<<"此矩阵的行列式为0,无解"<<endl;
Input();
}
}
}
void Matrix::Conversion(){
float temp[6][12];
for(int i=0;i<n;i++)//替身
for(int j=0;j<2*n;j++)
temp[i][j]=A[i][j];
LD_triangle(temp,n);//左下角变换0
Aii_Cto_1(temp,n); //对角变1
RU_triangle(temp,n);//右上角变换
Save_To_Result(temp,*this);
}
void LD_triangle(float temp[6][12],int n){
for(int i=0;i<n-1;i++){
if(temp[i][i]){//对角线元素不为0
if(temp[i][i]!=1.0)
if(int j=Find(temp,i,n)) Swap(temp,i,j,n);
for(int m=i+1;m<n;m++){
if(temp[m][i]){
float t=-(temp[m][i])/temp[i][i];
for(int p=0;p<2*n;p++){//R(m)+tRi
temp[m][p]=temp[m][p]+t*temp[i][p];
}
if(t>0)
cout<<"R"<<m+1<<"+"<<t<<"R"<<i+1<<":"<<endl;
else
cout<<"R"<<m+1<<t<<"R"<<i+1<<":"<<endl;
Display(temp,n,2*n);
}
else continue;
}
}
else {//若对角线元素为0
int m; for(m=i+1;m<n;m++){//
if(temp[m][i]){//使对角线元素非0
for(int p=0;p<n;p++)//Ri+Rm
temp[i][p]=temp[m][p]+temp[i][p];
break;
}
else continue;
}
if(m==n){ //可逆矩阵 不会出现此情况(对角元素为零,且此元素以下全为零)
//此情况 矩阵 行列式值为0
}
cout<<"R"<<i+1<<"+"<<"R"<<m+1<<endl;
Display(temp,n,2*n);
i--;
}
}
}
int Find(float temp[6][12],int i,int n){
for(int m=i+1;m<n;m++)
if(temp[m][i]==1.0)
return m;
return 0;
}
void Swap(float temp[6][12],int i,int j,int n){
cout<<"R"<<i+1<<"<-->R"<<j+1<<endl;
for(int m=0;m<2*n;m++){
temp[i][m]+=temp[j][m];
temp[j][m]=temp[i][m]-temp[j][m];
temp[i][m]-=temp[j][m];
}
Display(temp,n,2*n);
}
void Aii_Cto_1(float temp[6][12],int n){
for(int i=0;i<n;i++){
if(temp[i][i]!=1.0){
float t=1.0/temp[i][i];
cout<<"R"<<i+1<<"/"<<temp[i][i]<<endl;
for(int p=0;p<2*n;p++){//R(m)+tRi
temp[i][p]*=t;
}
Display(temp,n,2*n);
}
}
}
void RU_triangle(float temp[6][12],int n){
for(int i=n-1;i>0;i--){
for(int m=i-1;m>=0;m--){
if(temp[m][i]){
float t=-(temp[m][i])/(temp[i][i]);
for(int p=i;p<2*n;p++){ //R(m)+tempRi
temp[m][p]=temp[m][p]+t*temp[i][p];
}
if(t>0)
cout<<"R"<<m+1<<"+"<<t<<"R"<<i+1<<":"<<endl;
else
cout<<"R"<<m+1<<t<<"R"<<i+1<<":"<<endl;
Display(temp,n,2*n);
}
else continue;
}
}
}
void Display(float A[6][12],int m,int n){
for(int i=0;i<m;i++){
cout<<"|";
for(int j=0;j<n;j++){
cout<<setw(8)<<A[i][j];
if((j+1)%m==0)
cout<<" |";
}
cout<<endl;
}
cout<<endl;
}
void Save_To_Result(float temp[6][12],Matrix &D){
for(int i=0;i<D.n;i++)
for(int j=D.n;j<2*D.n;j++)
D.result[i][j-D.n]=temp[i][j];
}
bool Matrix::Cal_DetA(){
float temp[6][6];
for(int i=0;i<n;i++)
for(int j=0;j<n;j++)
temp[i][j]=A[i][j];
for(int i=0;i<n-1;i++){
if(temp[i][i]){//对角线元素不为0
for(int m=i+1;m<n;m++){
if(temp[m][i]){
float tem=-(temp[m][i])/temp[i][i];
for(int p=0;p<n;p++)//R(m)+tempRi
temp[m][p]=temp[m][p]+tem*temp[i][p];
}
else continue;
}
}
else {//若对角线元素为0
int m;
for(m=i+1;m<n;m++){//
if(temp[m][i]){//使对角线元素非0
for(int p=0;p<n;p++)//Ri+Rm
temp[i][p]=temp[m][p]+temp[i][p];
break;
}
else continue;
}
if(m==n){
Det_A=0;
return false;
}
i--;
}
}
Det_A=temp[0][0];//求对角积
for(int i=1;i<n;i++)
Det_A=Det_A*temp[i][i];
if(Det_A) return true;
else return false;
}
void Matrix::Out_Result(){
cout<<"Result:"<<endl;
for(int i=0;i<n;i++){
cout<<"|";
for(int j=0;j<n;j++){
cout<<setw(8)<<result[i][j];
}
cout<<" |"<<endl;
}
cout<<endl;
}
第一次修改结果:
为便于自己的使用,将矩阵修改为动态矩阵的形式,并在类中实现。
Invmatrix.h
#ifndef INVMATRIX_H
#define INVMATRIX_H
#include<iostream>
#include<iomanip>
#include<vector>
using namespace std;
#define N 3
//左下角变换0 若对角不为1元素下方元素为1交换两行
//对角变1
//右上角变换0
void LD_triangle(vector<vector<double>> &temp,int n);
void RU_triangle(vector<vector<double>> &temp,int n);
void Aii_Cto_1(vector<vector<double>> &temp,int n);
void Display(vector<vector<double>> &A,int m,int n);
int Find(vector<vector<double>> &temp,int i,int n);
void Swap(vector<vector<double>> &temp,int i,int j,int n);
class Matrix{
public:
Matrix(int _n);
void Conversion();
void Input(vector<vector<double>> &B);
bool Cal_DetA();
void Cheak_IsSolvable();
vector<vector<double>> Out_Result();
private:
int n; //阶
float Det_A; //|A|值 :是否存在逆矩阵
};
#endif // INVMATRIX_H
Invmatrix.cpp
#include <Invmatrix.h>
vector<vector<double>> A(3,vector<double>(6)); //全局矩阵;
vector<vector<double>> D(3,vector<double>(3));
vector<vector<double>> temp(3,vector<double>(6));
Matrix::Matrix(int _n)
{
n=_n;
Det_A=0;
}
void Matrix::Input(vector<vector<double>> &B){
for(int i=0;i<n;i++){
for(int j=0;j<n;j++){
A[i][j]=B[i][j];
}
}
int j=0;
for(int i=n;i<2*n;i++){
A[j][i]=1;
j++;
}
}
void Matrix::Cheak_IsSolvable(){
while(1){
if(Cal_DetA()){
cout<<"\n|A|="<<Det_A<<endl<<endl;
cout<<"(A|E)="<<endl;
Display(A,n,2*n);
break;
}
else{
cout<<"此矩阵的行列式为0,无解"<<endl;
}
}
}
void Matrix::Conversion(){
//vector<vector<double>> temp(n,vector<double>(2*n));
for(int i=0;i<n;i++)//替身
for(int j=0;j<2*n;j++)
temp[i][j]=A[i][j];
LD_triangle(temp,n);//左下角变换0
Aii_Cto_1(temp,n); //对角变1
RU_triangle(temp,n);//右上角变换
}
void LD_triangle(vector<vector<double>> &temp,int n){
for(int i=0;i<n-1;i++){
if(temp[i][i]){//对角线元素不为0
if(temp[i][i]!=1.0)
if(int j=Find(temp,i,n))
Swap(temp,i,j,n);
for(int m=i+1;m<n;m++){
if(temp[m][i]){
float t=-(temp[m][i])/temp[i][i];
for(int p=0;p<2*n;p++){//R(m)+tRi
temp[m][p]=temp[m][p]+t*temp[i][p];
}
if(t>0)
cout<<"R"<<m+1<<"+"<<t<<"R"<<i+1<<":"<<endl;
else
cout<<"R"<<m+1<<t<<"R"<<i+1<<":"<<endl;
Display(temp,n,2*n);
}
else continue;
}
}
else {//若对角线元素为0
int m;
for(m=i+1;m<n;m++){//
if(temp[m][i]){//使对角线元素非0
for(int p=0;p<n;p++)//Ri+Rm
temp[i][p]=temp[m][p]+temp[i][p];
break;
}
else continue;
}
if(m==n){ //可逆矩阵 不会出现此情况(对角元素为零,且此元素以下全为零)
//此情况 矩阵 行列式值为0
}
cout<<"R"<<i+1<<"+"<<"R"<<m+1<<endl;
Display(temp,n,2*n);
i--;
}
}
}
int Find(vector<vector<double>> &temp,int i,int n){
for(int m=i+1;m<n;m++)
if(temp[m][i]==1.0)
return m;
return 0;
}
void Swap(vector<vector<double>> &temp,int i,int j,int n){
cout<<"R"<<i+1<<"<-->R"<<j+1<<endl;
for(int m=0;m<2*n;m++){
temp[i][m]+=temp[j][m];
temp[j][m]=temp[i][m]-temp[j][m];
temp[i][m]-=temp[j][m];
}
Display(temp,n,2*n);
}
void Aii_Cto_1(vector<vector<double>> &temp,int n){
for(int i=0;i<n;i++){
if(temp[i][i]!=1.0){
float t=1.0/temp[i][i];
cout<<"R"<<i+1<<"/"<<temp[i][i]<<endl;
for(int p=0;p<2*n;p++){//R(m)+tRi
temp[i][p]*=t;
}
Display(temp,n,2*n);
}
}
}
void RU_triangle(vector<vector<double>> &temp,int n){
for(int i=n-1;i>0;i--){
for(int m=i-1;m>=0;m--){
if(temp[m][i]){
float t=-(temp[m][i])/(temp[i][i]);
for(int p=i;p<2*n;p++){ //R(m)+tempRi
temp[m][p]=temp[m][p]+t*temp[i][p];
}
if(t>0)
cout<<"R"<<m+1<<"+"<<t<<"R"<<i+1<<":"<<endl;
else
cout<<"R"<<m+1<<t<<"R"<<i+1<<":"<<endl;
Display(temp,n,2*n);
}
else continue;
}
}
}
void Display(vector<vector<double>> &A,int m,int n){
for(int i=0;i<m;i++){
cout<<"|";
for(int j=0;j<n;j++){
cout<<setw(8)<<A[i][j];
if((j+1)%m==0)
cout<<" |";
}
cout<<endl;
}
cout<<endl;
}
bool Matrix::Cal_DetA()
{
// vector<vector<double>> temp(n,vector<double>(n));
for(int i=0;i<n;i++){
for(int j=0;j<n;j++){
temp[i][j]=A[i][j];//复制矩阵A左侧(原始矩阵)
}
}
for(int i=0;i<n-1;i++){
if(temp[i][i]){//对角线元素不为0
for(int m=i+1;m<n;m++){
if(temp[m][i]){
float tem=-(temp[m][i])/temp[i][i];
for(int p=0;p<n;p++)//R(m)+tempRi
temp[m][p]=temp[m][p]+tem*temp[i][p];
}
else continue;
}
}
else {//若对角线元素为0
int m;
for(m=i+1;m<n;m++){//如果对角元素i为0;,那么判断下一行的此列元素是否为0,若不为零,则将该行元素分别与下一行的元素相加。
if(temp[m][i]){//使对角线元素非0
for(int p=0;p<n;p++)//Ri+Rm
temp[i][p]=temp[m][p]+temp[i][p];
break;
}
else continue;
}
if(m==n){
Det_A=0;//因为如果该对角元素为0,表示其上行的该列元素也为0,那么若果其下所有行在此列元素都为0,表名该列所有元素均为0,则该矩阵无解;
return false;
}
i--;//执行完该语句后,表示else语句执行完成,进入 for(int i=0;i<n-1;i++)循环
}
}
Det_A=temp[0][0];//求对角积
for(int i=1;i<n;i++)
Det_A=Det_A*temp[i][i];
if(Det_A) return true;
else return false;
}
vector<vector<double>> Matrix::Out_Result(){
for(int i=0;i<n;i++){
for(int j=0;j<n;j++){
D[i][j]=0;
}
}
for(int i=0;i<n;i++){
int p=0;
for(int j=n;j<2*n;j++){
D[i][p]=temp[i][j];
p++;
}
}
return D;
}
main.cpp
#include <Invmatrix.h>
#include<iostream>
#include<iomanip>
#include<vector>
using namespace std;
int main(){
cout<<"\n\t\t-------求逆矩阵(初等变换法)-------"<<endl<<endl;
vector<vector<double>> a(3,vector<double>(3));
a={{1,2,0},{1,1,0},{0,0,1}};
Matrix D(3);
D.Input(a);
D.Cheak_IsSolvable(); //可解
D.Conversion(); //变换
vector<vector<double>> M(3,vector<double>(3));
M=D.Out_Result(); //输出
for(int i=0;i<3;i++){
for(int j=0;j<3;j++){
cout<<M[i][j]<<endl;
}
}
return 0;
}
第二次修改:
删掉了一些不必要的成员函数,如friend void Save_To_Result()。因为要用到最终的可逆矩阵,因此将结果输出函数设置成vector<vector> Out_Result(),此外,使用该程序不需要进行每一个步骤的显示,只需得到最终的结果,因此去掉一系列的显示,精简程序:
Invmatrix.h
#ifndef INVMATRIX_H
#define INVMATRIX_H
#include<iostream>
#include<iomanip>
#include<vector>
using namespace std;
#define N 3
//左下角变换0 若对角不为1元素下方元素为1交换两行
//对角变1
//右上角变换0
void LD_triangle(vector<vector<double>> &temp,int n);
void RU_triangle(vector<vector<double>> &temp,int n);
void Aii_Cto_1(vector<vector<double>> &temp,int n);
int Find(vector<vector<double>> &temp,int i,int n);
void Swap(vector<vector<double>> &temp,int i,int j,int n);
class Matrix{
public:
Matrix(int _n);
void Conversion();
void Input(vector<vector<double>> &B);
bool Cal_DetA();
void Cheak_IsSolvable();
vector<vector<double>> Out_Result();
private:
int n; //阶
float Det_A; //|A|值 :是否存在逆矩阵
};
#endif // INVMATRIX_H
Invmatrix.cpp
扫描二维码关注公众号,回复:
11157613 查看本文章
#include <Invmatrix.h>
vector<vector<double>> A(3,vector<double>(6)); //全局矩阵;
vector<vector<double>> D(3,vector<double>(3));
vector<vector<double>> temp(3,vector<double>(6));
Matrix::Matrix(int _n)
{
n=_n;
Det_A=0;
}
void Matrix::Input(vector<vector<double>> &B){
for(int i=0;i<n;i++){
for(int j=0;j<n;j++){
A[i][j]=B[i][j];
}
}
int j=0;
for(int i=n;i<2*n;i++){
A[j][i]=1;
j++;
}
}
void Matrix::Cheak_IsSolvable(){
while(1){
if(Cal_DetA()){
cout<<"\n|A|="<<Det_A<<endl<<endl;
break;
}
else{
cout<<"此矩阵的行列式为0,无解"<<endl;
}
}
}
void Matrix::Conversion(){
//vector<vector<double>> temp(n,vector<double>(2*n));
for(int i=0;i<n;i++)//替身
for(int j=0;j<2*n;j++)
temp[i][j]=A[i][j];
LD_triangle(temp,n);//左下角变换0
Aii_Cto_1(temp,n); //对角变1
RU_triangle(temp,n);//右上角变换
}
void LD_triangle(vector<vector<double>> &temp,int n){
for(int i=0;i<n-1;i++){
if(temp[i][i]){//对角线元素不为0
if(temp[i][i]!=1.0)
if(int j=Find(temp,i,n))
Swap(temp,i,j,n);
for(int m=i+1;m<n;m++){
if(temp[m][i]){
float t=-(temp[m][i])/temp[i][i];
for(int p=0;p<2*n;p++){//R(m)+tRi
temp[m][p]=temp[m][p]+t*temp[i][p];
}
}
else continue;
}
}
else {//若对角线元素为0
int m;
for(m=i+1;m<n;m++){//
if(temp[m][i]){//使对角线元素非0
for(int p=0;p<n;p++)//Ri+Rm
temp[i][p]=temp[m][p]+temp[i][p];
break;
}
else continue;
}
if(m==n){ //可逆矩阵 不会出现此情况(对角元素为零,且此元素以下全为零)
//此情况 矩阵 行列式值为0
}
i--;
}
}
}
int Find(vector<vector<double>> &temp,int i,int n){
for(int m=i+1;m<n;m++)
if(temp[m][i]==1.0)
return m;
return 0;
}
void Swap(vector<vector<double>> &temp,int i,int j,int n){
for(int m=0;m<2*n;m++){
temp[i][m]+=temp[j][m];
temp[j][m]=temp[i][m]-temp[j][m];
temp[i][m]-=temp[j][m];
}
}
void Aii_Cto_1(vector<vector<double>> &temp,int n){
for(int i=0;i<n;i++){
if(temp[i][i]!=1.0){
float t=1.0/temp[i][i];
for(int p=0;p<2*n;p++){//R(m)+tRi
temp[i][p]*=t;
}
}
}
}
void RU_triangle(vector<vector<double>> &temp,int n){
for(int i=n-1;i>0;i--){
for(int m=i-1;m>=0;m--){
if(temp[m][i]){
float t=-(temp[m][i])/(temp[i][i]);
for(int p=i;p<2*n;p++){ //R(m)+tempRi
temp[m][p]=temp[m][p]+t*temp[i][p];
}
}
else continue;
}
}
}
bool Matrix::Cal_DetA()
{
// vector<vector<double>> temp(n,vector<double>(n));
for(int i=0;i<n;i++){
for(int j=0;j<n;j++){
temp[i][j]=A[i][j];//复制矩阵A左侧(原始矩阵)
}
}
for(int i=0;i<n-1;i++){
if(temp[i][i]){//对角线元素不为0
for(int m=i+1;m<n;m++){
if(temp[m][i]){
float tem=-(temp[m][i])/temp[i][i];
for(int p=0;p<n;p++)//R(m)+tempRi
temp[m][p]=temp[m][p]+tem*temp[i][p];
}
else continue;
}
}
else {//若对角线元素为0
int m;
for(m=i+1;m<n;m++){//如果对角元素i为0;,那么判断下一行的此列元素是否为0,若不为零,则将该行元素分别与下一行的元素相加。
if(temp[m][i]){//使对角线元素非0
for(int p=0;p<n;p++)//Ri+Rm
temp[i][p]=temp[m][p]+temp[i][p];
break;
}
else continue;
}
if(m==n){
Det_A=0;//因为如果该对角元素为0,表示其上行的该列元素也为0,那么若果其下所有行在此列元素都为0,表名该列所有元素均为0,则该矩阵无解;
return false;
}
i--;//执行完该语句后,表示else语句执行完成,进入 for(int i=0;i<n-1;i++)循环
}
}
Det_A=temp[0][0];//求对角积
for(int i=1;i<n;i++)
Det_A=Det_A*temp[i][i];
if(Det_A) return true;
else return false;
}
vector<vector<double>> Matrix::Out_Result(){
for(int i=0;i<n;i++){
for(int j=0;j<n;j++){
D[i][j]=0;
}
}
for(int i=0;i<n;i++){
int p=0;
for(int j=n;j<2*n;j++){
D[i][p]=temp[i][j];
p++;
}
}
return D;
}
main.cpp
#include <Invmatrix.h>
#include<iostream>
#include<iomanip>
#include<vector>
using namespace std;
int main(){
cout<<"\n\t\t-------求逆矩阵(初等变换法)-------"<<endl<<endl;
vector<vector<double>> a(3,vector<double>(3));
a={{1,2,0},{1,1,0},{0,0,1}};
Matrix D(3);
D.Input(a);
D.Cheak_IsSolvable(); //可解
D.Conversion(); //变换
vector<vector<double>> M(3,vector<double>(3));
M=D.Out_Result(); //输出
for(int i=0;i<3;i++){
for(int j=0;j<3;j++){
cout<<M[i][j]<<endl;
}
}
return 0;
}