1. 程式人生 > 其它 >矩陣求逆矩陣

矩陣求逆矩陣

因為座標系轉換實現需要求係數矩陣,所以這裡只介紹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 2 0 4 8 5 0 0 3 1 0 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);      //返回行列式的值  
}