说明
在写C++的程序时有时候需要使用到矩阵运算,而大部分时候又不至于使用加载matlab库的方式实现军阵矩阵运算的功能,下面提供一些矩阵运算的基本的API,其中很大一部分程序是参照别人别人的程序写的,本人只是做了一些整合的工作。
程序
vector<vector<double> > Testlib::creatmatrix(uint h, uint l) //创建一个值全部为0的矩阵
{
return creatmatrix(h,l,0);
}
vector<vector<double> > Testlib::creatmatrix(uint h, uint l, double a)//创建一个值全部为自定义值得矩阵
{
vector<vector<double>> v;
for (uint i = 0; i < h; i++)
{
vector<double>v1(l,a);
v.push_back(v1);
}
return v;
}
//矩阵A+矩阵B=矩阵C,并返回
vector<vector<double>> Testlib::plus(const vector<vector<double>>&A,const vector<vector<double>>&B)//两矩阵相加
{
if(A.empty()||B.empty())
{
qDebug()<<"矩阵不能为空"<<endl;
return {};
}
uint h=A.size();
uint l=A[0].size();
if(B.size()!=h||B[0].size()!=l)
{
qDebug()<<"两矩阵无法相加"<<endl;
return {};
}
vector<vector<double>> C;
C=creatmatrix( h, l);
for(uint i=0;i<h;i++)
{
for (uint j = 0; j < l; j++)
{
C[i][j]=A[i][j]+B[i][j];
if (abs(C[i][j])<1e-6)
{
C[i][j]=0.0;
}
}
}
return C;
}
//矩阵A-矩阵B=矩阵C,并返回
vector<vector<double>> Testlib::minus(const vector<vector<double>>&A,const vector<vector<double>>&B) //两矩阵相减
{
uint h=A.size();
uint l=A[0].size();
vector<vector<double>> C;
C=creatmatrix( h, l);
for(uint i=0;i<h;i++)
{
for (uint j = 0; j < l; j++)
{
C[i][j]=A[i][j]-B[i][j];
if (abs(C[i][j])<1e-6)
{
C[i][j]=0.0;
}
}
}
return C;
}
//矩阵A*矩阵B=矩阵C,并返回
vector<vector<double>> Testlib::multiply(const vector<vector<double>>&A,const vector<vector<double>>&B)
{
if(A.empty()||B.empty())
{
cout<<"矩阵不能为空"<<endl;
return {};
}
uint A_h=A.size();
uint A_l=A[0].size();
uint B_h=B.size();
uint B_l=B[0].size();
if(A_l !=B_h)
{
cout<<"两矩阵维数无法相乘"<<endl;
return {};
}
vector<vector<double>> C=creatmatrix(A_h,B_l);
for (uint i = 0; i < A_h; i++)
{
for (uint j = 0; j < B_l; j++)
{
C[i][j]=0;
for (uint k = 0; k < A_l; k++)
{
C[i][j] +=A[i][k]*B[k][j];
}
if (abs(C[i][j])<1e-6)
{
C[i][j]=0.0;
}
}
}
return C;
}
//矩阵A*num=矩阵B,并返回
vector<vector<double>> Testlib::multiply_num(const vector<vector<double>>&A,double num)
{
if(A.empty()){
cout<<"矩阵不能为空"<<endl;
return {};
}
uint A_h=A.size();
uint A_l=A[0].size();
vector<vector<double>> B=creatmatrix(A_h,A_l);
for (uint i = 0; i < A_h; i++)
{
for (uint j = 0; j < A_l; j++)
{
B[i][j]=num*A[i][j];
}
}
return B;
}
//矩阵A与矩阵B上下叠加获得新的矩阵C,并返回
vector<vector<double>> Testlib::matrix_overlaying_below(const vector<vector<double>>&A,const vector<vector<double>>&B)
{
//判断矩阵的列是否相等
uint A_h=A.size();
uint A_l=A[0].size();
uint B_h=B.size();
uint B_l=B[0].size();
if (A_l != B_l)
{
cout<<"叠加的矩阵列数不相等"<<endl;
return {};
}
//创建
vector<vector<double>> C=creatmatrix(A_h+B_h,A_l);
//将A传入
for (uint i = 0; i < A_h; i++)
{
for (uint j = 0; j < A_l; j++)
{
C[i][j]=A[i][j];
}
}
//将B传入
for (uint i = 0; i < B_h; i++)
{
for (uint j = 0; j < B_l; j++)
{
C[i+A_h][j]=B[i][j];
}
}
return C;
}
//矩阵A与矩阵B左右叠加,获得新的矩阵C,并返回
vector<vector<double>> Testlib::matrix_overlaying_beside(const vector<vector<double>>&A,const vector<vector<double>>&B)
{
//判断矩阵的列是否相等
uint A_h=A.size();
uint A_l=A[0].size();
uint B_h=B.size();
uint B_l=B[0].size();
if (A_h != B_h)
{
cout<<"叠加的矩阵行数不相等"<<endl;
return {};
}
//创建
vector<vector<double>> C=creatmatrix(A_h,A_l+B_l);
//将A传入
for (uint i = 0; i < A_h; i++)
{
for (uint j = 0; j < A_l; j++)
{
C[i][j]=A[i][j];
}
}
//将B传入
for (uint i = 0; i < B_h; i++)
{
for (uint j = 0; j < B_l; j++)
{
C[i][j+A_l]=B[i][j];
}
}
return C;
}
//输入矩阵A,输出矩阵A的转置矩阵AT
vector<vector<double>> Testlib::trans(const vector<vector<double>> &A)
{
vector<vector<double>> AT=creatmatrix(A[0].size(),A.size());
uint h=AT.size();
uint l=AT[0].size();
for (uint i = 0; i <h ; i++)
{
for (uint j = 0; j < l; j++)
{
AT[i][j]=A[j][i];
}
}
return AT;
}
//输入矩阵A,输出矩阵A的逆矩阵inv_A
vector<vector<double>> Testlib::inverse(const vector<vector<double>> &A)
{
if (A.size() != A[0].size())
{
cout<<"输入矩阵维数不合法"<<endl;
return {};
}
uint n=A.size();
vector<vector<double>> inv_A=creatmatrix(n,n);
vector<vector<double>> L=creatmatrix(n,n);
vector<vector<double>> U=creatmatrix(n,n);
vector<vector<double>> inv_L=creatmatrix(n,n);
vector<vector<double>> inv_U=creatmatrix(n,n);
//LU分解
//L矩阵对角元素为1
for (uint i = 0; i < n; i++)
{
L[i][i] = 1;
}
//U矩阵第一行
for (uint i = 0; i < n; i++)
{
U[0][i]=A[0][i];
}
//L矩阵第一列
for (uint i = 1; i < n; i++)
{
L[i][0]=1.0*A[i][0]/A[0][0];
}
//计算LU上下三角
for (uint i = 1; i < n; i++)
{
//计算U(i行j列)
for (uint j = i; j < n; j++)
{
double tem = 0;
for (uint k = 0; k < i; k++)
{
tem += L[i][k] * U[k][j];
}
U[i][j] = A[i][j] - tem;
if (abs(U[i][j])<1e-6)
{
U[i][j]=0.0;
}
}
//计算L(j行i列)
for (uint j = i ; j < n; j++)
{
double tem = 0;
for (uint k = 0; k < i; k++)
{
tem += L[j][k] * U[k][i];
}
L[j][i] = 1.0*(A[j][i] - tem) / U[i][i];
if (abs(L[i][j])<1e-6)
{
L[i][j]=0.0;
}
}
}
//L U剩余位置设为0
for(uint i=0;i<n;i++)
{
for(uint j=0;j<n;j++)
{
if(i>j)
{
U[i][j]=0.0;
}
else if(i<j)
{
L[i][j]=0.0;
}
}
}
//LU求逆
//求矩阵U的逆
for (int i=0;i<n;i++)
{
inv_U[i][i]=1/U[i][i];// U对角元素的值,直接取倒数
for (int k=i-1;k>=0;k--)
{
double s=0;
for (uint j=k+1;j<=i;j++)
{
s=s+U[k][j]*inv_U[j][i];
}
inv_U[k][i]=-s/U[k][k];//迭代计算,按列倒序依次得到每一个值,
if (abs(inv_U[k][i])<1e-6)
{
inv_U[k][i]=0.0;
}
}
}
//求矩阵L的逆
for (uint i=0;i<n;i++)
{
inv_L[i][i]=1; //L对角元素的值,直接取倒数,这里为1
for (uint k=i+1;k<n;k++)
{
for (uint j=i;j<=k-1;j++)
{
inv_L[k][i]=inv_L[k][i]-L[k][j]*inv_L[j][i];
if (abs(inv_L[k][i])<1e-6)
{
inv_L[k][i]=0.0;
}
}
}
}
inv_A=multiply(inv_U,inv_L);
return inv_A;
}
//打印矩阵
void Testlib::show_matrix(const vector<vector<double>> &A)
{
uint h=A.size();
uint l=A[0].size();
for (uint i = 0; i < h; i++)
{
for (uint j = 0; j < l; j++)
{
cout<<A[i][j]<<"\t";
}
cout<<endl;
}
}
最后
目前只实现了加单的矩阵运算的功能,至于一些复杂的功能暂时没有添加的想法。