因為坐標系轉換實現需要求系數矩陣,所以這里只介紹n*n維矩陣求逆矩陣的方法
單位矩陣E定義:
1 0 0 ... 0
0 1 0 ... 0
0 0 1 ... 0
0 0 0 ... 1
對角線上都是1,其他位置全是0
矩陣相乘:
n*n維矩陣A和B相乘(我們用Aij表示A矩陣第i行第j列的值)
(A*B)ij = Ai1*B1j+Ai2*B2j+Ai3*B3j+...+Ain*Bnj
逆矩陣定義:
假設一個n*n維矩陣A,如果存在一個n*n維矩陣B,使得A*B=E,那么就說B是A的逆矩陣A-1,同樣A也是B的逆矩陣B-1
一個矩陣的逆矩陣不是一定存在的(可以通過判斷行列式的值(也就是矩陣的模)等不等於0來判斷逆矩陣存不存在,等於0就不存在逆矩陣)
矩陣行列式求值方法:
我們需要了解等一下矩陣的初等變換:
(1) 交換矩陣的兩行(對調i,j,兩行記為ri,rj);(2) 以一個非零數k乘矩陣的某一行所有元素(第i行乘以k記為ri×k);(3) 把矩陣的某一行所有元素乘以一個數k后加到另一行對應的元素(第j行乘以k加到第i行記為ri+krj)。類似地,把以上的“行”改為“列”便得到矩陣初等列變換的定義,把對應的記號“r”換為“c”。矩陣的初等行變換與初等列變換合稱為矩陣的初等變換。
我們需要知道使用初等變換對矩陣的模的值的改變
第一類初等變換(換行換列)使行列式變號。
第二類初等變換(某行或某列乘k倍)使行列式變k倍。
第三類初等變換(某行(列)乘k倍加到另一行(列))使行列式不變。
上三角矩陣定義:
主對角線以下都是零的方陣稱為上三角矩陣。上三角矩陣具有行列式為對角線元素相乘、上三角矩陣乘以系數后也是上三角矩陣、上三角矩陣間的加減法和乘法運算的結果仍是上三角矩陣等性質。
示例:
1 5 6 20 4 8 50 0 3 10 0 0 5為一個上三角矩陣。
計算行列式或者矩陣的時候,可以行變換和列變換混着用嗎?
1、計算行列式時,可以同時施加第一、第三類初等行/列變換,施加第二類變換時需要將行列式乘上相應的系數
2、求矩陣的秩時,也即求相抵標准形時,可以施加三種初等行變換,或施加三種初等列變換(不可混用)
3、和單位矩陣拼在一起求逆矩陣時,豎着拼就只能用列變換,橫着拼就只能用行變換
4、解方程只能行變換
A矩陣的伴隨矩陣A*的求法:
假設A為n階矩陣,定義矩陣
為A的伴隨矩陣,記作
。
,Mij是矩陣A去掉i行j列后,所得矩陣的行列式。
求矩陣逆矩陣的兩種方法:
一、根據定義
A-1 = (1/|A|)*A*
求出來A矩陣的模和伴隨矩陣就可以
二、構造分塊矩陣(A|E)
把分塊矩陣(A|E)的A使用初等變換化成E,那么右邊的E在跟着A一起初等變換之后的矩陣就是A-1
原理(下圖來源於:https://wenku.baidu.com/view/62c266db094e767f5acfa1c7aa00b52acec79c0c.html):
C++代碼實現:
代碼來源於:https://blog.csdn.net/XX_123_1_RJ/article/details/39268041?locationNum=5&fps=1
代碼思想:
采用第二種方法計算逆矩陣
獲取行列式的值:把矩陣化為上三角矩陣之后按照定義求矩陣的模(注意,因為代碼中fun函數,把矩陣變成上三角矩陣使用了初等行變換的1,3規則,又因為第一條規則會影響到行列式值的正負,所以需要記錄一下行交換了幾次)
#include<iostream> #include<iomanip>
using namespace std; int const n=3; //確定矩陣的節數
/* 作者 星星筆記 */
int main() { void temp(double aa[],double bb[],int n); double fun(double array[n][n]); double a[n][n],b[n][2*n],c[n][n],det1,yinzhi; double bb; int i,j,kk=0,k,u; for(i=0;i<n;i++) //初始化一個輔助矩陣
for(j=0;j<2*n;j++) b[i][j]=0; //---------輸入原始矩陣---------------
cout<<"請輸入一個"<<n<<"節方陣"<<endl; for(i=0;i<n;i++) for(j=0;j<n;j++) cin>>a[i][j]; //把矩陣a復制給矩陣b
for(i=0;i<n;i++) for(j=0;j<n;j++) b[i][j]=a[i][j]; for(j=0;j<n;j++) b[j][n+j]=1; //------------------------------------ //------------測試查看---------- /* cout<<"a所對應的at矩陣b為:"<<endl; for(i=0;i<n;i++) for(j=0;j<2*n;j++) { cout<<setw(6)<<b[i][j]; kk=kk+1; if(kk%(2*n)==0) cout<<endl; } */
//---------------------------------- // det1=fun(a);//獲取行列式的值
for(i=0;i<n;i++) { // b[i][i] 等於 0 的情況
if(b[i][i]==0) for(j=i;j<n;j++) { if(b[j][i]!=0) temp(b[i],b[j],2*n); //交換兩行
} // b[i][i] 不等於 0 的情況
for(k=i+1;k<n;k++) { yinzhi = -1 * b[k][i] / b[i][i]; for(u=0; u < 2*n; u++) { b[k][u] = b[k][u] + b[i][u] * yinzhi; } } } det1 = fun(a);// 獲取行列式的值,把矩陣化為上三角矩陣之后按照定義求矩陣的模(注意,因為代碼中把矩陣變成上三角矩陣使用了初等行變換的1,3規則,又因為第一條規則會影響到行列式值的正負,所以需要記錄一下行交換了幾次)
if(det1 == 0) // 如果行列式的值為0 則是不可逆的。
{ cout<<"此矩陣不可逆:"<<endl; return 0; } if(det1 != 0) { for(i=0; i<n; i++) //左矩陣 的對角線 全部 轉化為 1
{ bb = b[i][i]; // bb 不會等於0 因為對角線有有一個為0 說明行列式的值為零,
for(j=0; j<2*n; j++) b[i][j] = b[i][j] / bb; } for(i=n-1; i>0; i--) for(k=0; k<i; k++) { bb = b[k][i]; for(u=0; u<2*n; u++) b[k][u] = b[k][u] - bb*b[i][u]; } } //------------測試查看---------- /* cout<<"變化后的at矩陣"<<endl; for(i=0;i<n;i++) for(j=0;j<2*n;j++) { cout<<setw(6)<<b[i][j]; kk=kk+1; if(kk%(2*n)==0) cout<<endl; } cout<<endl; */
//------------------------------
for(i=0; i<n; i++) for(j=0; j<n; j++) c[i][j] = b[i][j+n]; kk = 0; if(det1!=0) //輸出逆矩陣
{ cout<<"其可逆且其行列式的值det為:"<<det1<<endl<<endl; cout<<"可逆a矩陣的逆矩陣為c矩陣:"<<endl; for(i=0; i<n; i++) for(j=0; j<n; j++) { cout<<setw(15)<<c[i][j]; kk = kk+1; if(kk%n == 0) cout<<endl; } } return 0; } void temp(double aa[],double bb[],int n) { //交換數組指定的兩行,即進行行變換(具體為行交換)
int i; double temp1; for(i=0; i<n; i++) { temp1 = aa[i]; aa[i] = bb[i]; bb[i] = temp1; } } double fun(double array[n][n]) { int ii,jj,k,u; int iter = 0; double det1=1,yin; for(ii=0; ii<n; ii++) { if(array[ii][ii] == 0) for(jj=ii;jj<n;jj++) { if(array[jj][ii] != 0) { temp(array[ii],array[jj],n);//交換兩行
iter++; } } for(k=ii+1; k<n; k++) { yin = -1 * array[k][ii] / array[ii][ii]; for(u=0; u<n; u++) { array[k][u] = array[k][u] + array[ii][u] * yin; } } } for(ii=0;ii<n;ii++) det1 = det1 * array[ii][ii]; if(iter % 2 == 1) det1 = -det1; return (det1); //返回行列式的值
}