前言:

距离上一篇文章发布已经五天过去了,在这里先给一直等待的伙伴们说声抱歉,因为博主最近的事情很多,只好暂时停更,望大家理解!上一篇文章中,我们介绍了求解逆矩阵的方法,我提到,可逆矩阵可以定义除法。这一篇文章中,讨论一下怎样实现矩阵除法!

一、线性代数知识回顾:

事实上,矩阵没有 “除法” 这一概念,我们的 “除法” 实际上是用以下方式来定义的:

设矩阵,其中为可逆矩阵,满足以下等式:

变换得:

如果我们换一种写法,就成了:

这样就定义了矩阵除法,我把它称为 “左除”。类似的,若:

我们这时如果定义出  ,那么就成为了 “右除”。

本篇以 “左除” 为例,给出算法与代码。

之前我们给出过矩阵的乘法和求矩阵的逆的方法,因此我们可以很简单地写出求矩阵除法的代码,只需调用两个函数即可,但是,我们还是要挑战一下!优化一下算法:

之前提到过线性代数一个定理:

对一个矩阵左乘一个可逆矩阵相当于对这个矩阵作一系列初等行变换

求解  就相当于根据 等式  来求解矩阵  ,我们看下面的推导:

由  可知: 

这就说明,对等式  两边都左乘 ,相当于作一系列初等行变换,观察等式,这个初等行变换将等式左边的矩阵  化为矩阵  ,将等式右边的矩阵  变为 ,也就是矩阵  。

所以对矩阵  做初等行变换化为  的同时,对矩阵  做同样的初等行变换,就将矩阵  变成了我们要求解的矩阵 

二、代码实现:

由于本次博客算法与求逆矩阵类似,所以博主就不在这里设置算法设计的环节了,直接进入代码,有的细节在代码里面有注释。

类的定义:

class Mat
{
public:int m = 1, n = 1; //行数和列数double mat[N][N] = { 0 };  //矩阵开始的元素Mat() {}Mat(int mm, int nn){m = mm; n = nn;}void create();//创建矩阵void Print();//打印矩阵bool div(Mat a,Mat b);//求 a.mat/b.mat
};

其中 div 函数做除法运算,在求逆矩阵代码的基础上修改一下就可以了,代码如下:

bool Mat::div(Mat a,Mat b)
{if (b.n != b.m){cout << "奇异矩阵不能作分母!" << endl;return false;}if (b.n != a.m){cout << "这两个矩阵无法相除!" << endl;return false;}//下来进行自上而下的初等行变换,使得矩阵 b.mat 变成单位上三角矩阵for (int i = 1; i <= b.m; i++) //注意这里要 i<=m,和之前的上三角矩阵有不同{                         //因为要判断最后一行化为上三角矩阵的最后一行最后一列元素是否为 0//寻找第 i 列不为零的元素int k;for (k = i; k <= b.m; k++){if (fabs(b.mat[k][i]) > 1e-10) //满足这个条件时,认为这个元素不为0break;}if (k <= b.m)//说明第 i 列有不为0的元素{if (k != i)//说明第 i 行 第 i 列元素为零,需要和其他行交换{//交换第 i 行和第 k 行所有元素for (int j = i; j <= b.n; j++)//从第 i 个元素交换即可,因为前面元素都为零{//使用mat[0][j]作为中间变量交换元素b.mat[0][j] = b.mat[i][j]; b.mat[i][j] = b.mat[k][j]; b.mat[k][j] = b.mat[0][j];}for (int j = 1; j <= a.n; j++)//从第 1 个元素交换{a.mat[0][j] = a.mat[i][j]; a.mat[i][j] = a.mat[k][j]; a.mat[k][j] = a.mat[0][j];}}double c = b.mat[i][i];//倍数//将矩阵 a.mat 的主对角线元素化为 1for (int j = i; j <= b.n; j++)//从第 i 个元素开始,前面元素都为 0{b.mat[i][j] /= c;}for (int j = 1; j <= a.n; j++)//给分子矩阵作同样的变换{//从第 1 个元素开始a.mat[i][j] /= c;}for (int j = i + 1; j <= b.m; j++){//注意本来为 -b.mat[j][i]/b.mat[i][i],因为b.mat[i][i]等于 1,则不需要除它c = -b.mat[j][i];for (k = i; k <= b.n; k++)//从第 i 个元素开始{b.mat[j][k] += c * b.mat[i][k];//第 i 行 b 倍加到第 j 行}for (k = 1; k <= b.n; k++)//从第 1 个元素开始{a.mat[j][k] += c * a.mat[i][k];}}}else{cout << "奇异矩阵不能作分母!" << endl;return false;}}//下面进行自下而上的行变换,将 b.mat 矩阵化为单位矩阵for (int i = b.m; i > 1; i--){for (int j = i - 1; j >= 1; j--){double c = -b.mat[j][i];b.mat[j][i] = 0; //实际上是通过初等行变换将这个元素化为 0,for (int k = 1; k <= a.n; k++){//通过相同的初等行变换来变换右边矩阵a.mat[j][k] += c * a.mat[i][k];}}}//下面代码将经过初等行变换的分子赋值给类中的矩阵m = a.m; n = a.n;for (int i = 1; i <= m; i++){for (int j = 1; j <= n; j++){mat[i][j] = a.mat[i][j];}}return true;
}

我们在这篇博客中只给出了 “左除” ,有兴趣的朋友们可以试着自己做一下 “右除” ,基本方法是一样的,自己写一下可以更好地掌握并且锻炼自己的代码能力。这里给出完整代码:

#include<iostream>
#include <cmath>
#define N 10
using namespace std;
class Mat
{
public:int m = 1, n = 1; //行数和列数double mat[N][N] = { 0 };  //矩阵开始的元素Mat() {}Mat(int mm, int nn){m = mm; n = nn;}void create();//创建矩阵void Print();//打印矩阵bool div(Mat a,Mat b);//求 a.mat/b.mat
};void Mat::create()
{for (int i = 1; i <= m; i++){for (int j = 1; j <= n; j++){cin >> mat[i][j];}}
}
void Mat::Print()
{for (int i = 1; i <= m; i++){for (int j = 1; j <= n; j++){cout << mat[i][j] << "\t";}cout << endl;}
}bool Mat::div(Mat a,Mat b)
{if (b.n != b.m){cout << "奇异矩阵不能作分母!" << endl;return false;}if (b.n != a.m){cout << "这两个矩阵无法相除!" << endl;return false;}//下来进行自上而下的初等行变换,使得矩阵 b.mat 变成单位上三角矩阵for (int i = 1; i <= b.m; i++) //注意这里要 i<=m,和之前的上三角矩阵有不同{                         //因为要判断最后一行化为上三角矩阵的最后一行最后一列元素是否为 0//寻找第 i 列不为零的元素int k;for (k = i; k <= b.m; k++){if (fabs(b.mat[k][i]) > 1e-10) //满足这个条件时,认为这个元素不为0break;}if (k <= b.m)//说明第 i 列有不为0的元素{if (k != i)//说明第 i 行 第 i 列元素为零,需要和其他行交换{//交换第 i 行和第 k 行所有元素for (int j = i; j <= b.n; j++)//从第 i 个元素交换即可,因为前面元素都为零{//使用mat[0][j]作为中间变量交换元素b.mat[0][j] = b.mat[i][j]; b.mat[i][j] = b.mat[k][j]; b.mat[k][j] = b.mat[0][j];}for (int j = 1; j <= a.n; j++)//从第 1 个元素交换{a.mat[0][j] = a.mat[i][j]; a.mat[i][j] = a.mat[k][j]; a.mat[k][j] = a.mat[0][j];}}double c = b.mat[i][i];//倍数//将矩阵 a.mat 的主对角线元素化为 1for (int j = i; j <= b.n; j++)//从第 i 个元素开始,前面元素都为 0{b.mat[i][j] /= c;}for (int j = 1; j <= a.n; j++)//给分子矩阵作同样的变换{//从第 1 个元素开始a.mat[i][j] /= c;}for (int j = i + 1; j <= b.m; j++){//注意本来为 -b.mat[j][i]/b.mat[i][i],因为b.mat[i][i]等于 1,则不需要除它c = -b.mat[j][i];for (k = i; k <= b.n; k++)//从第 i 个元素开始{b.mat[j][k] += c * b.mat[i][k];//第 i 行 b 倍加到第 j 行}for (k = 1; k <= b.n; k++)//从第 1 个元素开始{a.mat[j][k] += c * a.mat[i][k];}}}else{cout << "奇异矩阵不能作分母!" << endl;return false;}}//下面进行自下而上的行变换,将 b.mat 矩阵化为单位矩阵for (int i = b.m; i > 1; i--){for (int j = i - 1; j >= 1; j--){double c = -b.mat[j][i];b.mat[j][i] = 0; //实际上是通过初等行变换将这个元素化为 0,for (int k = 1; k <= a.n; k++){//通过相同的初等行变换来变换右边矩阵a.mat[j][k] += c * a.mat[i][k];}}}//下面代码将经过初等行变换的分子赋值给类中的矩阵m = a.m; n = a.n;for (int i = 1; i <= m; i++){for (int j = 1; j <= n; j++){mat[i][j] = a.mat[i][j];}}return true;
}int main()
{Mat a(3, 4), b(3, 3);cout << "请输入 " << a.m << "*" << a.n << " 的矩阵:" << endl;a.create();cout << "请输入 " << b.m << "*" << b.n << " 的矩阵:" << endl;b.create();Mat c;if (c.div(a, b))c.Print();return 0;
}

由于博主最近事情特别多,在接下来的一段时间里很可能会不更新,望大家见谅!

若有不足之处,欢迎大家指正!

线性代数代码实现(六)矩阵除法(C++)相关推荐

  1. 1 数列分块入门_线性代数入门——关于分块矩阵的典型证明题与综合题

    系列简介:这个系列文章讲解线性代数的基础内容,注重学习方法的培养.线性代数课程的一个重要特点(也是难点)是概念众多,而且各概念间有着千丝万缕的联系,对于初学者不易理解的问题我们会不惜笔墨加以解释.在内 ...

  2. Matlab 矩阵论 矩阵分解的计算实现(六)矩阵的正交三角分解

    Matlab 矩阵论 矩阵分解的计算实现(六)矩阵的正交三角分解 本来matlab中自带了做正交三角分解的函数,[U,R]=qr(A),U R为分解结果.但是这样使用只会有结果没有中间过程,所以写了一 ...

  3. 【MATLAB数学建模算法代码(六)之遗传算法】

    MATLAB数学建模算法代码(六) 遗传算法: 根据自己需要修改参数即可!!! %遗传算法主程序 %Name:genmain05.m function genmain() tic; clear clf ...

  4. Apollo代码学习(六)—模型预测控制(MPC)_follow轻尘的博客-CSDN博客_mpc代码

    Apollo代码学习(六)-模型预测控制(MPC)_follow轻尘的博客-CSDN博客_mpc代码

  5. iOS 编写高质量Objective-C代码(六)

    级别: ★★☆☆☆ 标签:「iOS」「Block」「Objective-C」 作者: MrLiuQ 审校: QiShare团队 前言: 这几篇文章是小编在钻研<Effective Objecti ...

  6. 线性代数之向量、矩阵、行列式、列向量的计算

    线性代数之向量.矩阵.行列式.列向量的计算 标签(空格分隔): 线性代数 1.向量与实数的的乘法: 2∗[23]=[46] 2 ∗ [ 2 3 ] = [ 4 6 ] 2*\left[\begin{m ...

  7. 应用线性代数简介 - 向量,矩阵和最小二乘法 By Stephen Boyd and Lieven Vandenberghe

    Introduction to Applied Linear Algebra – Vectors, Matrices, and Least Squares 应用线性代数简介 - 向量,矩阵和最小二乘法 ...

  8. 线性代数(第六版)同济大学 习题一 (1-4题)个人解答

    线性代数(第六版)同济大学 习题一(1-4题) 1. 利用对角线法则计算下列三阶行列式: \begin{aligned}&1. \ 利用对角线法则计算下列三阶行列式:&\end{ali ...

  9. 线性代数(第六版)同济大学 习题一 (5-6题)个人解答

    线性代数(第六版)同济大学 习题一(5-6题) 5. 求解下列方程: \begin{aligned}&5. \ 求解下列方程:&\end{aligned} ​5. 求解下列方程:​​ ...

最新文章

  1. 「小程序JAVA实战」微信开发者工具helloworld(三)
  2. Eclipse工作空间还原到最初状态
  3. React Fiber 原理介绍
  4. Transformer又又又升级了?
  5. Visual Studio 2008 中使用插件Extjs提示的方法
  6. LeetCode 面试题57 - II(剑指offer) 和为s的连续正数序列
  7. win7 部署tomcat
  8. linux编译mesa,如何在Ubuntu 16.04,17.10中安装Mesa 17.3.3
  9. 深入分析八种前景看好的物联网业务形态
  10. 四大科技支撑大健康生态 360保险输出标准化、定制化两大核心力
  11. 从技术、服务到共创 声网 Agora 携手合作伙伴共建 RTC 生态
  12. pwm 正弦波_正弦波逆变器和修正波逆变器的区别
  13. Unity资源替换工具,旧模型替换新模型,替换GUID,替换meta文件,文件丢失等问题
  14. AKM e-compass获取G-sensor的方法
  15. 多功能扫描仪设备 可识别护照
  16. Information Bottleneck 信息瓶颈
  17. TCP复位报文的发送
  18. 关于大象,冰箱和软件项目报价的故事
  19. 恒源云(GPUSHARE)_可构建AI的「AI」诞生?
  20. 以数据智能引领产业数字化,滴普科技宣布完成5000万美元A+轮融资

热门文章

  1. Vue 中 iconfont 使用
  2. 期刊论文发表时作者简介怎么写
  3. 用友uap开发 nc63,65中的参照开发
  4. 从乐高上我们可以学到什么?
  5. 智拓SMARTCHART全明星团队区块链分享会成功举办
  6. mysql主备删除备数据,mysql 互为主备 宕机 数据丢失_Devops部署-mysql主备多从搭建...
  7. 打破千篇一律,DIY属于自己独一无二的商城
  8. MVC的理解和优缺点的总结
  9. 祝贺:奈雪的茶创始人彭心荣获“深圳首届十大金口碑人物”称号
  10. 光伏逆变器MPPT功能