【线性代数 C++】求逆矩阵

devtools/2024/9/24 21:26:19/
  • 对于 n n n矩阵 A A A,如果有 n n n矩阵 B B B,使 A B = B A = E AB=BA=E AB=BA=E,则说 A A A是可逆的,并把 B B B称为 A A A矩阵.
  • A A A的逆矩阵记作 A − 1 A^{-1} A1,则 B = A − 1 B=A^{-1} B=A1.
  • ∣ A ∣ ≠ 0 \begin{vmatrix}A\end{vmatrix} \neq 0 A =0,则 A A A可逆,且 A − 1 = 1 ∣ A ∣ A ∗ A^{-1}= \frac{1}{\begin{vmatrix}A \end{vmatrix}}A^* A1=A1A.
  • 上式中, ∣ A ∣ \begin{vmatrix}A\end{vmatrix} A A A A的行列式, A ∗ A^* A A A A的伴随矩阵.

1 矩阵行列式求值

1.1 定义

  • n n n阶方阵 A A A的元素构成的行列式(各元素位置不变),称为 A A A的行列式,记作 ∣ A ∣ \begin{vmatrix}A \end{vmatrix} A d e t A detA detA.

1.2 C++代码

为便于管理函数,建立行列式类CDeterminant.

  • 求行列式值的两种途径:一是根据行列式定义、二是利用代数余子式.
  • 在CDeterminant类中增加两个成员函数GetCetValByDef()和GetDetValByRem(),相关代码参考【线性代数|行列式定义及其值】和【线性代数 | C++】行列式按行(列)展开。

2 求伴随矩阵

2.1 定义

  • 行列式 ∣ A ∣ \begin{vmatrix}A\end{vmatrix} A 各元素的代数余子式 A i j A_{ij} Aij构成的如下矩阵 A ∗ = [ A 11 A 21 ⋯ A n 1 A 12 A 22 ⋯ A n 2 ⋮ ⋮ ⋮ A 1 n A 2 n ⋯ A n n ] , A^*=\begin{bmatrix}A_{11} & A_{21} & \cdots & A_{n1} \\A_{12} & A_{22} & \cdots & A_{n2} \\ \vdots & \vdots && \vdots \\A_{1n} & A_{2n} &\cdots & A_{nn}\end{bmatrix}, A= A11A12A1nA21A22A2nAn1An2Ann ,称为矩阵 A A A伴随矩阵.
  • 注意:伴随矩阵 A ∗ A^* A中元素的位置与对应行列式 ∣ A ∣ \begin{vmatrix}A\end{vmatrix} A 中元素的位置呈转置关系.

2.2 C++代码

2.2.1 求余子式
  • 由定义可知,求伴随矩阵,需先求行列式各元素的代数余子式.
  • 求代数余子式,需先求余子式.
  • 故,在CDeterminant类中增加一个求行列式余子式的成员函数GetDetRem().
//在CDeterminant.h声明成员函数
static bool GetDetRem
(const vector<vector<double>> &vvDetInput, //原始行列式int i,  //待求余子式元素的行号int j,  //待求余子式元素的列号vector<vector<double>> &vvDetRet    //求得的余子式
);
//在CDeterminant.cpp中定义成员函数
bool CDeterminant::GetDetRem
(const vector<vector<double>> &vvDetInput, int i, int j,vector<vector<double>> &vvDetRet
)
{if (false == IsDet(vvDetInput))//形参是否符合行列式格式要求return false;vvDetRet.clear();vvDetRet = vvDetInput;//删除元素所在的行vvDetRet.erase(vvDetRet.cbegin() + i);for (int i = 0; i < vvDetRet.size(); i++){//删除元素所在的列vvDetRet[i].erase(vvDetRet[i].cbegin() + j);}return true;
}
2.2.2 求伴随矩阵
  • 在CMatrix类中添加GetAdjointMat函数,用于求伴随矩阵.其思路是:
    1. 按列逐行取得矩阵的元素;
    2. 求相应的余子式
    3. 对余子式求值
    4. 求代数余子式
    5. 将代数余子式的值,按行填入新矩阵
    6. 得到伴随矩阵
//在CMatrix.h中声明成员函数
static bool GetAdjointMat
(
const vector<vector<double>> &vvMatInput,
vector<vector<double>> &vvMatRet
);
//在CMatrix.cpp中定义成员函数
bool CMatrix::GetAdjointMat
(const vector<vector<double>> &vvMatInput,vector<vector<double>> &vvMatRet
)
{//判断vector变量是否符合行列式格式if (false == CDeterminant::IsDet(vvMatInput))return false;vvMatRet.clear();vector<double> vTemp;//临时存储伴随矩阵的行元素vector<vector<double>> vvDetTemp;//临时存储余子式double iDetValTemp;//临时存储余子式的值//按列循环for (int i = 0; i < vvMatInput[0].size(); i++){vTemp.clear();//按行循环for (int j = 0; j < vvMatInput.size(); j++){//求余子式vvDetTemp.clear();CDeterminant::GetDetRem(vvMatInput, j, i, vvDetTemp);//余子式求值iDetValTemp = 0;CDeterminant::GetDetValByDef(vvDetTemp, iDetValTemp);//求代数余子式iDetValTemp = (pow(-1, i + j) * iDetValTemp);//代数余子式的值填入新矩阵的行元素中vTemp.push_back(iDetValTemp);}  //行元素填入新矩阵vvMatRet.push_back(vTemp);  }  return true;
}

3 求逆矩阵

  • 利用前面求得的 ∣ A ∣ \begin{vmatrix}A \end{vmatrix} A A ∗ A^* A,按照公式 A − 1 = 1 ∣ A ∣ A ∗ A^{-1}= \frac{1}{\begin{vmatrix}A \end{vmatrix}}A^* A1=A1A,可以求得 A A A的逆矩阵.
  • 在CMatrix类中增加GetInverseMat函数,以实现上述功能.
//在CMatrix.h中声明函数
static bool GetInverseMat
(
const vector<vector<double>> &vvMatInput,
vector<vector<double>> &vvInverseMat
);
//在CMatrix.cpp中定义函数
bool CMatrix::GetInverseMat
(const vector<vector<double>> &vvMatInput,vector<vector<double>> &vvInverseMat
)
{if (false == CDeterminant::IsDet(vvMatInput))return false;//方阵行列式值不等于0时,方阵可逆double fDetVal;CDeterminant::GetDetValByDef(vvMatInput, fDetVal);if (0 == fDetVal)return false;  fDetVal = 1.0 / fDetVal;vector<vector<double>> vvMatTemp;GetAdjointMat(vvMatInput, vvMatTemp);//求伴随矩阵vvInverseMat.clear();MatMulti(fDetVal, vvMatTemp, vvInverseMat);//求数与矩阵相乘return true;
}

4 测试

//在test.cpp中测试
#include <iostream>
#include <iomanip>
#include <vector>#include "CMatrix.h"using namespace std;bool PrintMat
(const vector<vector<double>> &vvMat
)
{for (int i = 0; i < vvMat.size(); i++){for (int j = 0; j < vvMat[i].size(); j++){cout << setw(5) << vvMat[i][j];}cout << endl;}return true;
}int main()
{vector<vector<double>> vvMatA{{ 1, 2, 3},{ 2, 2, 1},{ 3, 4, 3}};vector<vector<double>> vvMatRet;if (false == CMatrix::GetInverseMat(vvMatA, vvMatRet)){cout << "计算失败" << endl;}else{PrintMat(vvMatRet);} return 0;
}

在这里插入图片描述


  1. 引用文献:《工程数学 线性代数(第五版)》同济大学数学系编,高等教育出版社.
  2. 以上为个人学习、练习的记录,如有错误,欢迎指正.

http://www.ppmy.cn/devtools/16528.html

相关文章

图论应用——拓扑排序

拓扑排序的原理和宽度优先搜索差不多 #include <iostream> #include <cstring> #include <algorithm> using namespace std;const int N 100010; int n,m; int h[N],e[N],ne[N],idx; int q[N],d[N];void add(int a,int b) {e[idx]b,ne[idx]h[a],h[a]idx; }…

IO多路复用

select函数实现 #include <mystdio.h> #define PORT 8888 #define IP "192.168.124.18" int main(int argc, const char *argv[]) { //创建流式套接字文件 int sfd socket(AF_INET,SOCK_STREAM,0);//AF_INET IPv4 SOCK_STREAM 流式套接字 if(…

AR模块中通用对账的优化尝试

背景&#xff1a; 用户在唯品会下单后&#xff0c;是可以自由选择不同支付方式进行支付的&#xff0c;支付后&#xff0c;支付系统会将一笔收款单传送给AR&#xff0c;AR财务可以从此处看到收款情况。但是&#xff0c;真实的资金是按照不同支付方式&#xff0c;由银行或者其他渠…

离开A页面时,取消A页面的axios接口数据请求

需求&#xff1a;从A页面跳转至B页面时&#xff0c;要取消A页面的axios请求&#xff1b;有时候&#xff0c;我们可能需要在发送请求后取消它&#xff0c;比如用户在请求还未完成时离开了当前页面或者执行了其他操作&#xff0c;本文将介绍如何在使用 Axios 发送请求时取消这些请…

vscode中对 python 快速增加header 描述

在首选项→配置用户代码片段→python 然后再 Code/User/snippets/python.json文件中写入 {// Place your snippets for python here. Each snippet is defined under a snippet name and has a prefix, body and // description. The prefix is what is used to trigger the …

分享:9.3版本无缝导入AVEVA PDMS高版本工程12.0,12.1,E3D

9.3版本可以无缝导入AVEVA PDMS的工程。 UKP3d导入AVEVA PDMS工程的方法 http://47.94.91.234/forum.php?modviewthread&tid163583&fromuid6 (出处: 优易软件-工厂设计软件专家) &#xff08;从AVEVA PDMS导出时元件和等级的功能我们正做收尾工作&#xff0c;到时可以…

MacOS通过命令行开启关闭向日葵远程控制的后台服务

categories: [Tips] tags: MacOS Tips 写在前面 经常有小伙伴问我电脑相关的问题, 而解决问题的一个重要途径就是远程了. 关于免费的远程工具我试过向日葵和 todesk, 并且主要使用向日葵, 虽然 MacOS 下要设置很多权限, 但是也不影响其丝滑的控制. 虽然用着舒服, 但是向日葵…

服务器排障(Linux,Windows)

一&#xff0e;计算机的启动流程 二&#xff0e;系统服务 三&#xff0e;运行级别 四&#xff0e;运行级别被修改 五&#xff0e;Root密码被遗忘 六&#xff0e;设置Grub密码 七&#xff0e;设置bios密码 一、计算机启动流程 1、bios加电自检 对计算机的硬件进行检测&a…