C++ 数学与算法系列之高斯消元法求解线性方程组

news2024/11/16 21:51:29

1. 前言

什么是消元法?

消元法是指将多个方程式组成的方程组中的若干个变量通过有限次地变换,消去方程式中的变量,通过简化方程式,从而获取结果的一种解题方法。

消元法主要有代入消元法加减消元法整体消元法换元消元法构造消元法因式分解消元法常数消元法利用比例性质消元法等。

对方程式消元时,是基于如下的初等行变换规则:

  • 改变方程组方程式的顺序,或者说无论先求解方程组中哪一个方程式,不影响方程组的解。
  • 对一个方程式中的所有系数乘以或除以某一个非零数,不影响方程组的解。
  • 方程式之间可以倍乘后相加或相减,不影响解。

其中最常用的为代入消元法加减消元法,简要介绍一下。

代入消元法

如求解 2x+3y=10x+y=4; 2 个方程式中的 x ,y变量时。

可以把第 2 个方程式变换成 x=4-y

然后代入到第 1 个方程中,2(4-y)+3y=10。可求解出 y=2,x=2

加减消元法

还是求解如上的方程组。

可以把第2 个方程式乘以 2 后再去减第 1 个方程式,或者说让第 1 个方程式减去第 2 个方程式乘以 2

2x+3y-2x-2y=10-8。可以求解 y=2

本文主要和大家聊聊高斯消元法,高斯(Gauss)消元法也称为简单消元法,是求解一般线性方程组的经典算法。

2. 高斯消元法

在理解高斯消元化之前,先理解几个基本概念:

什么是增广矩阵?

增广矩阵是线性代数中的概念,如下线性方程组:

2.png

使用每个方程式的系数构建的矩阵,称为系数矩阵,表示为:

3.png

用方程式的系数结果构建的矩阵称为方程组的增广矩阵。如下图所示:

4.png

当方程组中的每一个方程的结果都为 0时, 即 b1=b2=b3=b4……bm=0,称这样的方程组为齐次线性方程组

2.1 高斯消元思想

高斯消元的基本思想:

  • 对于一个有 n个变量、有n个方程式的方程组。

2.png

  • 把方程组中除了第 1 个方程式外的其它方程式中的x1 消去,同理,再把除了第 2 个方程式以下的方程组中其它方程式中的 x2 消去,依次类推,直到最后 1 个方程式中只留下 xn

  • 目的:通过一系列的变换,让增广矩阵变换成一个稀疏的行阶梯矩阵

现通过具体的案例,理解高斯消元法。

如求解如下图所示的方程组:

1.jpg

  • 用方程组中的所有方程式的系数和结果构建增广矩阵,此矩阵有 3 行,为了描述方便,用 r1表示第 1 行,r2 表示第 2 行,r3 表示第 3 行

2.jpg

  • 利用初等行变换规则将增广矩阵转换成行阶梯矩阵

    首先,定位至r1行(当前行)的第 1列(col=1),以行(列号不变)扫描方式(从上向下)查找到本列中绝对值最大的数据,然后把最大值所在的行和当前行交换。如下图,因当前行所在列中的值就是最大值,故不需要交换。

    Tips:为什么要交换?是不是一定要交换行?

5.png

  • 消元过程,从方程组角度而言,消去第 1 个方程后面 x1变量。从矩阵角度而言,让r1后面行中的 col列中的数据变为 0。 如消去 r2、r3col列中数据,可以使用倍数相加(减)变换方案,消元表达式:r2=r2*5-r1*2、r3=r3*5+r1

10.png

11.png

  • 定位到r2行的第 2 列(col=2)。逻辑如上,以行扫描方式查找到本列中绝对值最大的数据,然后把最大值所在的行和当前行交换。因当前行的值 29最大,不需要交换。

12.png

  • 消去 r3中的 x2变量,让r3行中只保留x3变量。 消元表达式:r3=r3*29-r2*23

13.png

  • 最终会得到一个行阶梯的系数矩阵,最后可以对矩阵以反序方式迭代求解。如下图所示:

14.png

  • 最终可以得到 x3=1,x2=-2,x1=2

问题思考

变换过程中,是不是一定需要交换行

答案:不一定。

当方程组中的方程式不多时,换不换行其实并不重要。如下方程组。

8.png

其增广矩阵如下图所示。

9.png

可以先消去r2行中的x1变量。即r2=r2*-2*r3

15.png

再消去r1行中的x2变量。即r1=r1*2+r2

16.png

使用消元求解过程中,没有对行交换,同样能求解方程组中各变量的值。但是,当方程组中方程式的数量非常多时,如果不提供统一的处理规则,则无法对大量数据进行迭代处理。

算法设计的本质是发现或者为数据提供统一的逻辑处理单元。前文所述高斯消元法中之所以交换行,是保证最后生成稀疏上三角矩阵的前提,从而让算法更稳定。

求解方程组时,其解有 3 种情况:

  • 无解,如果最后一行形如: {0,0,0,……0 ,val!=0} 则无解。
  • 唯一解。消元后,最后生成标准的上三角形矩阵
  • 无穷解。消元后,不是标准的上三角形矩阵即不可确定。

2.2 编程实现

如下代码的主题是讨论高斯消元算法,只考虑了无解唯一解 2 种情况且假设所有解都是整数。

#include <iostream>
#include <cmath>
using namespace std;
class GaussXy {
	private:
		//矩阵的行数,方程组中方程的数量
		int row;
		//矩阵的列数(系数和结果数量)
		int col;
		//二维数组
		int **matrix;
		//存储方程组的结果
		int *result;
		/*
		* 初始化数据
		*/
		void init() {
			string tips="请输入方程的系数和结果的值";
			for(int i=0; i<row; i++) {
				cout<<tips<<endl;
				for(int j=0; j<col; j++) {
					cin>>this->matrix[i][j];
				}
			}
		}
		/*
		*查找列值最大的行
		* curRow:当前行
		* col:列号
		*/
		int  getMaxRow(int curRow,int col ) {
			//行扫描查找当前列中的最大值
			int maxRow=curRow;
			for(int i=curRow+1; i<this->row; i++) {
				if( fabs( this->matrix[i][col]) > fabs( this->matrix[maxRow][col] ) ) {
					maxRow=i;
				}
			}
			return maxRow;
		}
		/*
		*求两数最小公倍数
		*/
		int gbs(int num,int num_) {
			//存储相乘结果
			int res=num*num_;
			int temp=0;
			if(num<num_) {
				temp=num;
				num=num_;
				num_=temp;
			}
			//辗转相除求最大公约数
			while(num_!=0) {
				temp=num_;
				num_=num % num_;
				num=temp;
			}
             //返回最小公倍数
			return res /  num;
		}
		/*
		*交换行
		*/
		void swapRow(int curRow,int maxRow) {
			int* tmp=this->matrix[curRow];
			this->matrix[curRow]=this->matrix[maxRow];
			this->matrix[maxRow]=tmp;
		}
    
	public:
		/*
		*构造函数
		*/
		GaussXy(int row,int col) {
			this->row=row;
			this->col=col;
			//结果数组
			this->result=new int[this->row*2];
			for(int i=0; i<this->row*2; i++)
				this->result[i]=1;
			//通过输入数据构建矩阵
			this->matrix=new int*[row];
			for(int i=0; i<row; i++) {
				this->matrix[i]=new int[col];
			}
			//初始化矩阵
			this->init();
		}
    
		/*
		*显示矩阵
		*/
		void showMatrix() {
			cout<<"\n矩阵信息"<<endl;
			for(int i=0; i<row; i++) {
				for(int j=0; j<col; j++) {
					cout<< this->matrix[i][j]<<"\t";
				}
				cout<<endl;
			}
		}
    
		/*
		* 核心代码:高斯消元
		*/
		void  gaussXy() {
			//最大行号
			int maxRow=0;
             //行扫描
			for(int curRow=0,curCol=0; curRow<this->row; curRow++,curCol++) {
				maxRow=0;
				//行扫描查找最大值行
				maxRow= this->getMaxRow(curRow,curCol);
				//交换行
				if(maxRow!=curRow) this->swapRow(curRow,maxRow);
				//将 curRow 以下的行和 curRow 行消元
				for(int nextRow=curRow+1; nextRow<this->row; nextRow++) {
					if( this->matrix[nextRow][curCol] !=0 ) {
						//找两数绝对值的最小公倍数
						int gbs= this->gbs(fabs(this->matrix[curRow][curCol]) ,fabs(this->matrix[nextRow][curCol] ) );
						//倍数
						int curRowBs= gbs/fabs( this->matrix[curRow][curCol] );
						//倍数
						int nextRowBs=gbs / fabs(this->matrix[nextRow][curCol]) ;
						//一正一负
						if( this->matrix[curRow][curCol] * this->matrix[nextRow][curCol] < 0 )curRowBs=-curRowBs;
						//列扫描,消元行中的变量
						for ( int j=curCol; j<this->col; j++) {
							this->matrix[nextRow][j]=this->matrix[nextRow][j]*nextRowBs - this->matrix[curRow][j]*curRowBs;
						}
					}
				}
			}
		}
    
		/*
		*求解
		*/
		void getResult() {
			//如果最后一行形如: {0,0,0,……0 val!=0} 则无解
			if( this->matrix[this->row-1][this->col-2]==0 &&  this->matrix[this->row-1][this->col-1]!=0 )
				cout<<"无解"<<endl;
             int idx=0;
			//存储每行最后一列的值
			int res=0;
			int curCol=0;
			//如果是严格的行阶梯矩阵,则有唯一解
			for(int curRow=this->row-1; curRow>=0; curRow--) {
				int idx=this->row-1;
				int res=this->matrix[curRow][this->col-1];
				int curCol=this->col-2;
				for(; curCol>=0; curCol--) {
					//为零结束
					if( this->matrix[curRow][curCol]==0) break;
					//减去
					res-=this->matrix[curRow][curCol]*this->result[idx--];
				}
				//补回来
				res+=this->matrix[curRow][curCol+1];
                 //只取整数
				this->result[curRow]=  res / this->matrix[curRow][curCol+1] ;
			}
			//输出结果
			cout<<"\n结果:"<<endl;
			for(int i=0; i<this->row; i++ )
				cout<<"x"<<i+1<<":"<<this->result[i]<<endl;
		}
};
//测试
int main() {
	GaussXy* gaussXy=new GaussXy(3,4);
	cout<<"---------------------";
	gaussXy->showMatrix();
    //高斯消元
	gaussXy->gaussXy();
	cout<<"---------------------";
	gaussXy->showMatrix();
	gaussXy->getResult();
	return 0;
}

输出结果:

17.png

3. 总结

本文讨论了高斯消元法的算法思想,基于此思想编码实现了对方程组的求解。本文旨在讲清楚高斯消元的核心逻辑,有兴趣者可在此代码的基础上继续研究、扩展。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/125874.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【C/C++ SOCKET编程】实现服务器客户端的简单通信

什么是SOCKET Socket又称"套接字"&#xff0c;应用程序通常通过"套接字"向网络发出请求或者应答网络请求&#xff0c;使主机间或者一台计算机上的进程间可以通讯。 TCP/IP协议 从字面意义上讲&#xff0c;有人可能会认为 TCP/IP 是指 TCP 和 IP 两种协议…

Hive环境安装搭建

目录 Hive安装 MySQL安装 配置Hive元数据库到MySQL Hive安装 软件包 0积分免费下载&#xff1a; hive环境安装所需软件包-Hive文档类资源-CSDN下载 将软件包拖进虚拟机中 将jar包解压到目录 给目录文件夹名改为hive 配置环境变量 输入命令&#xff1a; vim /etc/profile …

数据滚动大屏:Stimulsoft Dashboards.WIN 2023.1.2

Stimulsoft Dashboards.WIN 是一组组件&#xff0c;您可以使用这些组件将分析添加到您的应用程序中。WinForms 和 WPF 的仪表板 Stimulsoft Dashboards.WIN 是一个功能齐全的工具&#xff0c;用于在仪表板上转换、分析、分组、过滤、排序和显示数据。它与 .NET Framework 4.5 及…

科创板智能家居第一股,萤石网络昨日上市

2022年12月28日&#xff0c;杭州萤石网络股份有限公司(以下简称“萤石网络”)成功登陆上海证券交易所科创板&#xff0c;证券代码为688475。值得一提的是&#xff0c;萤石网络是登陆科创板的第500家企业。 在上市仪式上&#xff0c;萤石网络董事长、总经理蒋海青表示&#xff0…

医药信息咨询公司排名TOP10是怎么进行收费的?

随着我国医药行业的飞速发展&#xff0c;市场竞争也是越发的激烈&#xff0c;作为产业链中的医药信息咨询公司作用也愈加明显&#xff0c;医药信息咨询公司以提供医药行业的战略咨询、项目尽调、产品立项评估、行业赛道/细分市场机会评估、专利服务、新产品上市服务、新药产品特…

QA | 关于高级硬件在环(HIL)想要了解的十个问题

HiL&#xff08;Hardware-in-the-Loop&#xff09;硬件在环仿真测试系统是采用实时处理器运行仿真模型来模拟受控对象&#xff08;比如&#xff1a;汽车、航空飞机等设备&#xff09;的运行状态&#xff0c;以此判断电控模块的性能。 Q1&#xff1a;什么是HIL&#xff1f; 硬…

分享20个Javascript中的数组方法,收藏

什么是数组&#xff1f;与其他编程语言中的数组一样&#xff0c;Array对象允许在一个变量名称下存储多个项的集合&#xff0c;并且具有用于执行常见数组操作的成员。 声明数组 我们可以用两种不同的方式声明数组。 使用新阵列 使用new Array&#xff0c;我们可以指定希望存在…

GitHub下载量10W,最新23版Java岗面试攻略,涵盖25个技术栈

年底失业&#xff0c;机会也不多&#xff0c;短时间内想找到合适工作是几乎不可能的。身体好点在家&#xff0c;主要建议大家就做两件事&#xff1a; 第一&#xff1a;整理工作经验&#xff0c;制定新年求职计划。等一些不错的公司放出新的hc&#xff0c;市场情况一回暖&#…

淘宝首页serverless升级后的质量保障方案

本文主要介绍了serverless 架构升级在淘宝首页的应用&#xff0c;新架构对底层所依赖的容器、环境资源等与之前相比差异较大&#xff0c;并且对应的预发、安全生产、生产等环境&#xff0c;与旧架构的完全隔离。背景阿里巴巴集团大淘宝技术全面推进云原生2.0战役——serverless…

wordpress企业主题推荐

WordPress制造企业主题推荐 国潮好物&#xff0c;配国产主题&#xff0c;为中国制造加油、助力&#xff0c;适合生产、加工、制造业官网的WordPress主题。 演示 https://www.jianzhanpress.com/?p4358 wordpress服务行业网站模板推荐 浅绿色小清新wordpress网站模板&#x…

软件测试期末复习(一)试题及答案

一、单项选择题&#xff08;每空 2 分&#xff0c;共 40 分&#xff09; 1&#xff0e;软件测试的目的:&#xff08; c &#xff09; A. 避免软件开发中出现的错误 B. 发现软件开发中出现的错误 C. 尽可能发现并排除软件中潜藏的错误&#xff0c;提高软件的可靠性 D. 修改软件…

Axure绘制流程图

相信大家在日常的工作中经常会绘制流程图&#xff0c;基本常见的绘制流程图的工具有Visio、亿图等。但是如果大家使用的是axure制作的产品prd的话&#xff0c;这些流程图的源文件全部需要进行存储&#xff0c;一旦丢失就需要重新画一遍&#xff0c;这样是很不方便。那么有没有一…

JDBC API详解

文章目录入门案例DriverManagerConnectionStatementResultSetPreparedStatement数据库连接池完整代码入门案例 package jdbc;import java.sql.*;public class connectionTest {public static void main(String[] args) throws ClassNotFoundException, SQLException {//1.注册…

Revit二次开发小技巧(十六)寻找最短路径

最近遇到一个需求&#xff0c;指定两个配电箱&#xff0c;然后找到两个配电箱之间最短的桥架路径。运用了Dijkstra算法去计算最短路径&#xff0c;以配电箱实体、三通、四通为节点&#xff0c;简化中间弯头计算的方式。 背景 选择起点和终点的配电箱&#xff0c;找到最短的桥架…

RingUI + JCEF开发IDEA插件

文章目录RingUI知识储备示例插件实现逻辑开发环境开发流程新建一个IDEA插件项目新建一个前端项目验证前端项目丰富前端项目丰富插件内容RingUI This collection of UI components aims to provide all the necessary building blocks for web-based products built inside JetB…

向 Windows 高级用户进阶,这 5 款效率工具帮你开路

工欲善其事&#xff0c;必先利其器。作为全球最多人使用的桌面操作系统&#xff0c;Windows 的使用效率与我们的工作学习息息相关。今天&#xff0c;小编就为大家整理了 10 款提高效率的利器&#xff0c;让你的 Windows 更具生产力。 1.文件预览——Seer MacOS 有一个非常方便…

优雅草YYC松鼠短视频2022年12月28日更新v5.1.6版本更新·修复因为消息提醒二开导致菜单栏无法显示·进一步完善推送

优雅草YYC松鼠短视频2022年12月28日更新v5.1.6版本更新修复因为消息提醒二开导致菜单栏无法显示进一步完善推送 更新日志 修复因为消息提醒二开导致菜单栏无法显示 继续进一步开发消息推送 目前消息推送登录以及推送判断返回刷新仍存在问题在开发中 目前goeasy官方也在更新关…

数据劫持基础

数据劫持数据劫持原理。属性描述符Object.defineProperty官网响应式原理![在这里插入图片描述](https://img-blog.csdnimg.cn/b9f900484f314334a0dc6139428b397c.png)getter和setterObject.defineProperty的不足proxy工作原理总结数据劫持原理。 数据劫持&#xff0c;指的是在…

Find My资讯|苹果 Find My 找到因交通事故坠崖的一名女子

美国加州圣贝纳迪诺县消防局在其官方 Facebook 更新动态&#xff0c;表示在接到家属报警&#xff0c;通过苹果 Find My 功能追踪家人的 iPhone&#xff0c;成功营救出在圣贝纳迪诺山区的 18 号高速公路上坠崖的一名妇女。 圣贝纳迪诺县消防局在帖子中表示这名妇女在圣诞节那天…

多线程与高并发(三)

【 day3课前复习 】&#xff1a; 【AtomicInteger】&#xff1a; 原子性——都是用CAS机制来实现。 【 expected , update 】: //有时候也会写三个值——你要修改的那个对象。 expected——期望值。&#xff08;旧值&#xff09; update——更新值。&#xff08;新值&#…