高斯列主消元法 求非齐次线性方程组 C语言实现代码

2023-11-13

高斯列主元素消去法是由高斯消去法改进的算法

下面浅浅分享一下本人对该方法的理解

Ax = b

先说高斯消去法,感觉基本的思路就跟我们手算非齐次线性方程组差不多,在线性代数中,我们求解方程组都是这种思路,消元的过程相当于是,由系数矩阵A和非齐次项b得到的增广矩阵做行变换,化为行阶梯型,最后在由下往上回代,求出每一个未知数的过程。

举例如下所示:

\Large\begin{cases}x_1+2x_2+3x_3=-1\\x_1+5x_2+3x_3=-1\\2x_1+3x_2+x_3=-1\end{cases}

 由系数矩阵和非齐次项拼成的增广矩阵如下所示

\Large\begin{bmatrix} 1 & 2 & 3 & -1\\ 1& 5 & 3 & -1\\ 2& 3 & 1 & -1 \end{bmatrix}

我们作初等行变化将其化为行阶梯型如下

 \Large\begin{bmatrix} 1 & 2 & 3 & -1\\ 0 & 3 & 0 & 0\\ 0 & 0 & -5 & 1 \end{bmatrix}

到上一步之后我们就完成了消元的过程

解出未知数一步步回代就可以得到解向量如下

\Large\begin{bmatrix}-0.4\\0\\-0.2\end{bmatrix}

 当然在数学上,这样的非线性方程组要有解,必须要求系数矩阵的秩等于增广矩阵的秩,不过数学上的东西就不在本篇讨论范围内了。

上面叙述的步骤在计算机程序中是很容易实现的,但考虑下面的矩阵消元。

\Large\begin{bmatrix} 0 & -3 & 0 & 0\\ 1 & 5 & 3 & -1\\ 2 & 3 & 1 & -1 \end{bmatrix}

可以看到,问题就在于,第一行第一列的元素为0,是无法消去它下方的任何数在,在计算机中也会因为0作除数而无法求解。而且就算这样的主对角线上的元素不为0,但如果元素很小的话,就会因为它是除数,而引起其他元素数量级及舍入误差的急剧增大,从而导致计算结果不可靠。

这种情况下,就产生了列主元素消去法,它的基本思想是在每步消元时,在第k列主对角线元素及其下方的元素中选取绝对值最大的元素作为主元,进行该步的消去。即体现为一个行列互换。

以上面的矩阵距离,我们用列主元素消去法逐步化简,你便会明白具体的操作步骤。

\Large\begin{bmatrix} 0 & -3 & 0 & 0\\ 1 & 5 & 3 & -1\\ 2 & 3 & 1 & -1 \end{bmatrix}

我们先将第一行第一列的元素0与它下方列所有的元素作比较,即比较0,1,2三个元素,找出他们中绝对值最大的元素,即2,我们就以2作为主元进行消去步骤,即将第①行与第③行互换,得

 \Large\begin{bmatrix} 2 & 3 & 1 & -1\\ 1 & 5 & 3 & -1\\ 0 & -3 & 0 & 0 \end{bmatrix}

然后用2将下方的元素消为0,得

\Large\begin{bmatrix} 2 & 3 & 1 & -1\\ 0 & 3.5 & 2.5 & -0.5\\ 0 & -3 & 0 & 0 \end{bmatrix}

下面是第二行第二列的元素的消去,即3.5,与其下方的元素作比较,注意是下方元素,即不包括3,只有3.5与-3,进行绝对值比较,3.5已经是绝对值最大的元素了,所以不需要行变换,就以3.5做主元进行消去。

依次循环上面的步骤,直到完成全部主元的消去,之后便是和高斯消去法一样的回代求解过程了。

可以看出高斯列主元素消去法的思想是很简单但却十分有效的。

——————————————————————————————

下面给出我用C语言实现的代码,主要函数为EMCP()函数,大家可根据需要自行修改或使用

#include <stdio.h>
#include <stdlib.h>

/*
	———————————————— 
	说明:
	———————————————— 
	高斯列主消元法主函数为 EMCP()
	函数原型为:
	Double * EMCP(void * mat,double * vec)
	具体用法见main()函数
	
	使用时将main函数前的所有函数复制到自己程序的main函数前面 
	根据main中说明的使用方法使用本函数
	 
	复制时 所有前置函数 缺一不可,且顺序不可随意调换
	最后一个PrintMat()是用来打印二维数组的,可要可不要 
	————————————————
	@猿力觉醒 
*/

//前置函数 绝对值函数 
double _Abs(double value){
	if(value < 0)
		return -value;
	else{
		return value;
	}
}

//前置函数 获取矩阵对应元素地址 
double * _Get(void * mat,int i,int j,int N){
	return ((double*)mat + i*N) + j;
} 

//前置函数 行变换 交换矩阵的第a行与第b行 
void _MatSwap(void * mat,int a,int b,int N){
	double temp;
	
	for(int i=0;i<N;i++){
		temp = *_Get(mat,a,i,N);
		
		*_Get(mat,a,i,N) = *_Get(mat,b,i,N);
		
		*_Get(mat,b,i,N) = temp;
	}
} 
void _VecSwap(double * vec,int a,int b,int N){
	double temp;
	
	temp = vec[a];
	
	vec[a] = vec[b];
	
	vec[b] = temp;
}
void _Swap(void * mat,double * vec,int a,int b,int N){
	_MatSwap(mat,a,b,N);
	_VecSwap(vec,a,b,N); 
}

//前置函数 行变换 将矩阵的第a行的k倍加到第b行 
void _MatIk2J(void * mat,int a,double k,int b,int N){
	double temp;
	
	for(int i=0;i<N;i++){
		temp = *_Get(mat,a,i,N) * k;
		
		*_Get(mat,b,i,N) += temp;
	}
}
void _VecIk2J(double * vec,int a,double k,int b,int N){
	double temp;
	
	temp = k * vec[a];
	
	vec[b] += temp;
}
void _Ik2J(void * mat,double * vec,int a,double k,int b,int N){
	_MatIk2J(mat,a,k,b,N);
	_VecIk2J(vec,a,k,b,N);
}

//高斯列主消元法 函数主体 
double * EMCP(void * mat,double * vec,int N){
	//消元 	
	for(int i=0;i<N-1;i++){
		//寻找列主元 
		int maxEle = i;//列主元索引 
		for(int k=i+1;k<N;k++){
			if(_Abs(*_Get(mat,k,i,N)) > _Abs(*_Get(mat,maxEle,i,N)))
				maxEle = k;
		}
		if(*_Get(mat,i,i,N) == 0.0)
			return NULL;//某列主元为0,方程无解,返回NULL 
		else{
			_Swap(mat,vec,maxEle,i,N);//行交换 
		}
		
		for(int j=i+1;j<N;j++){
			//将列主元下的元素全部消为0	
			_Ik2J(mat,vec,i,-((*_Get(mat,j,i,N))/(*_Get(mat,i,i,N))),j,N);			
		}		
	}
	
	double * v_out = (double*)malloc(sizeof(double)*N);
	
	//回代 
	for(int i=N-1;i>=0;i--){
		//解出最下方可解的元 
		v_out[i] = vec[i]/(*_Get(mat,i,i,N));
		
		//对于已经解出的元,从vec中消去该元 
		for(int j=i-1;j>=0;j--){
			vec[j] -= v_out[i]*(*_Get(mat,j,i,N));
		}
	}
	
	return v_out; 
}

//打印输出矩阵 
void PrintMat(void * mat,int N){
	for(int i=0;i<N;i++){
		for(int j=0;j<N;j++){
			printf("%.2lf",*_Get(mat,i,j,N));
			printf("  ");
		}
		printf("\n\n");
	}
}


//以下为测试用main函数,示意函数使用方法 
int main(void){
	//求解线性方程组 Ax = b 的问题(对应有限元 Ku = F 的求解) 
	//	mat为系数矩阵,即为 A;vec为非齐次项,即为 b 
	double mat[3][3] = {{1,2,3},{1,5,3},{2,3,1}};
	double vec[3] = {-1,-1,-1};
	
	//	EMCP()函数会更改传入的系数矩阵mat与非齐次项vec 
	//	故此处为了演示用法重定义了一模一样的mat与vec 
	double _mat[3][3] = {{1,2,3},{1,5,3},{2,3,1}};
	double _vec[3] = {-1,-1,-1};

	printf("Answer of question: Ax = b\n");
	printf("\n\n");
	
	printf("A is:\n");
	PrintMat(mat,3);
	printf("\n");
	
	printf("b = \n");
	for(int i=0;i<3;i++){
		printf("%.2lf  ",vec[i]);
	}
	printf("\n\n");
	
	//【关键处】 
	//下面的语句展示了调用EMCP的用法 	
	//	double * EMCP(mat,vec,N) 一共需要3个参数
	//	第一个参数mat为系数矩阵,传入C语言中的二维数组的名字即可
	//	第二个参数vec为非齐次项的列向量,传入C语言中的一维数组名字即可 
	//	第三个参数N为方程的阶数
	//
	//	使用时必须保证mat与vec维数一致 
	double * v_out = EMCP(_mat,_vec,3);
	//EMCP()返回一个双精度一维数组 
	//	即解向量数组
	//	上面 v_out 与一维数组等价 
	//	可以使用如 v_out[i] 的形式访问每个元素 
	//
	
	PrintMat(_mat,3);
	
	if(v_out){
		printf("Output Vector x:\n");
		for(int i=0;i<3;i++){
			printf("%.5lf  ",v_out[i]);
		}
		printf("\n\n");
	
		printf("As the following equaltion:\n");
		
		for(int i=0;i<3;i++){
		printf("|");
			for(int j=0;j<3;j++){
				printf("%+4.2lf  ",*_Get(mat,i,j,3));
			}
			printf("\b\b|  [%+8.5lf]  =  |%+4.2lf|",v_out[i],vec[i]);
			printf("\n");
		}
	}
	else{
		printf("No Solution!");
	} 
}

 

 

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

高斯列主消元法 求非齐次线性方程组 C语言实现代码 的相关文章

  • Chroom书签同步

    Chroom自带书签管理 而且有些管理书签的插件 我感觉自带书签管理栏就能满足我的个人需求 但是有一个问题 当我换了电脑后 原来的书签怎么同步 我为什么要使用Chroom 用其他浏览器广告太多了 比如360 也试着使用国内的其他浏览器 感觉

随机推荐

  • 如何在vscode配置php开发环境

    3 下载并安装vscodehttps code visualstudio com 下载的是一个压缩包 将其解压至一个目录 4 在vscode中安装调试插件右侧栏中点击扩展 输入xdebug 出来的php debug 点击安装 在菜单栏 文件
  • C++ 常用容器及其使用方法

    文章目录 本章内容概述 一 Vector 1 构造函数 2 增加函数 3 删除函数 4 属性函数 二 Unordered map 1 构造函数 2 增加函数 3 删除函数 4 属性函数 三 Stack 1 构造函数 2 访问方式 3 增加函
  • python: pandas与numpy(一)创建DataFrame数组与数组的简单操作

    目录 前言 1 创建Series数组 2 创建DataFrame数组 使用字典来创建DataFrame 使用列表来创建DataFrame 使用Series数组创建DataFrame 使用numpy函数创建DataFrame 3 在DataF
  • logback.xml

  • Mayor‘s posters(线段树染色)

    题目链接 Mayor s posters 2023 4 13 更新了代码 修复了错误的离散化长度 已在代码中注出 大致题意 有n个人依次贴海报 第i个海报的范围是 li ri 后面贴的海报会覆盖掉之前贴的海报 问 最终还能看到多少张海报 解
  • java的3大注释快捷键大全

    单行注释 行注释 一般用于单行或者少量代码 快捷键 光标 ctrl 或者 多行注释 块注释 一般用于多行或者大量代码 快捷键 选中 ctrl shift 文档注释 方法或类注释 一般用于对类和方法的说明 快捷键 光标 回车键 EnTer
  • 蓝桥杯Java必备基础知识总结大全【3W字】持续更新中

    本文会持续更新 如果对您有帮助的话可以点点关注 双击 本人2021年蓝桥杯C B组国二 今年转战Java 并整理此文 希望能够对大家有所帮助 第一次写这么长的文章 可能有的地方写的不是很好 还请大家多多谅解 我会持续进行改进并且更新 更新
  • 海思(MPP)媒体处理软件平台(3)-----VDEC

    sample vdec 视频解码 测试环境 在HI3531D开发板上运行 查看代码使用VSCode 运行 nfsroot mpp sample vdec sample vdec please choose the case which yo
  • [激光原理与应用-68]:光耦继电器、固态继电器、延时继电器、PLC开关信号

    一 PLC开关信号 备注 PLC需要的是开关信号 闭合或断开 不需要TTL电平信号 二 激光器输出信号 三 固态激光器工作原理 四 光耦继电器原理 五 光耦 延时 继电器原理 六 差分转单端原理
  • 排列组合知识

    排列组合的定义 排列 就是从n个元素中取出m个元素 按照一定的顺序排成一列 看到没 是要有顺序排成一列的 组合 也是从n个元素中取出m个元素 只不过是组成一个组 并不要求排成一列 只要组的成员不同就可以了 公式如下 例题 哪里用得上排列组合
  • 【Markdown】图片缩放

    01 原图表示 语法为 替代文本 图片链接地址 其中 替代文本是在无法显示图片时显示的替代文本 而图片链接是指向图片的URL或相对路径 例如 插入Panda图片 panda https img blog csdnimg cn e5f32e4
  • 亚信科技AntDB数据库专家参加向量数据库首次技术标准研讨会

    2023年7月19日下午 中国通信标准化协会大数据技术标准推进委员会数据库与存储工作组 CCSA TC601 WG4 联合中国信通院数据库应用创新实验室 CAICT DBL 在线上召开 向量数据库技术要求 标准首次研讨会 本次会议由中国信通
  • 单端反激——隔离型DC/DC变换器的设计及仿真

    单端反激 隔离型DC DC变换器的设计及仿真 技术指标 1 原理分析 2 参数设计 3 仿真验证 技术指标 输入电压 V s m i n
  • Spring Boot 2.2.6 源码之旅二十五SpringMVC源码之RequestMappingHandlerMapping的初始化三

    Spring Boot 2 2 6 源码之旅二十五SpringMVC源码之RequestMappingHandlerMapping的初始化三 简单流程图 MappingRegistry的一些映射 urlLookup一键多值的url和Requ
  • 那些会阻碍程序员成长的细节[4]

    照例 如果没有读过之前的系列 在这里可以先回顾一下 那些会阻碍程序员成长的细节 1 那些会阻碍程序员成长的细节 2 那些会阻碍程序员成长的细节 3 本文共 1637 字 预计阅读时间 5 分钟 不愿意跟领导走的近 是不是有这样的体会 凡事有
  • 【python标准库学习】re模块

    1 什么是re 正则表达式一门相对通用的语言 在python中也有对正则表达式的支持 那就是的内置re模块 正则表达式就是一系列的规则去匹配字符串然后进行相应的操作 这些规则网上一搜一大片 而re则是运用正则表达式来提供一系列的功能强大的接
  • Vue中如何进行打包与部署?

    Vue中如何进行打包与部署 Vue是一款流行的JavaScript框架 它提供了丰富的功能和组件 可以用于构建现代化的Web应用程序 在开发Vue应用程序时 我们通常需要进行打包和部署 本文将介绍Vue中的打包和部署 包括使用Webpack
  • STL list合并

    知识点来源 cplusplus STL list 网上很多关于list的操作很少有提及到怎么合并 要说这个合并几乎是每个数据结构课提及到的O 1 操作的必修知识点 同时还有人甚至搞不清楚什么叫Merge 归并 和合并 Union 归并的意思
  • linux 查看端口连接数

    一 查看哪些IP连接本机 netstat an 二 查看TCP连接数 1 统计80端口连接数 netstat nat grep i 80 wc l 2 统计httpd协议连接数 ps ef grep httpd wc l 3 统计已连接上的
  • 高斯列主消元法 求非齐次线性方程组 C语言实现代码

    高斯列主元素消去法是由高斯消去法改进的算法 下面浅浅分享一下本人对该方法的理解 Ax b 先说高斯消去法 感觉基本的思路就跟我们手算非齐次线性方程组差不多 在线性代数中 我们求解方程组都是这种思路 消元的过程相当于是 由系数矩阵A和非齐次项