高斯消元求解线性方程组——线性代数


前言

大一刚刚学习了线性代数,我们都知道线代中最容易出错的就是计算,那我们用计算不会出错的计算机来求解这个线性方程组是一个怎样的体验呢?


一、什么是高斯消元?

高斯消元法(或译:高斯消去法),是线性代数规划中的一个算法,可用来为线性方程组求解。

二、算法思路

1.要求解的例题

输入一个包含n个方程n个未知数的线性方程组。

方程组中的系数为实数。

求解这个方程组。

输入:
第一行两个整数n(1 < n < 100)
后n行输入一个n*(n + 1)的增广矩阵
输出:
答案共n行表示x1~xn(保留两位小数,当无解或有无穷多组解时输出相应提示)

2.详细思路

首先分析解的情况:我们都知道线性方程组有三种解的情况,我们在此仅计算有唯一解的答案,当我们遇到无解或者无穷多组解时输出相应提示。

求解方程组时,我们要把方程化为最简形,而我们的算法就是要实现此过程。

消元时,首先找到适合的一行交换到当前所计算的一行,并将该行首列之下全跟新为0,重复操作直到最后一行或出现非唯一解情况。
在这里插入图片描述

//记当前修改到了r行c列
int t = r;//暂时存储所修改到的行数
for(int i = r + 1; r <= n; i ++ )
	if(fabs(a[i][c]) > fabs(a[t][c]))
		t = i;//找到未修改的第c列最大值的行
for(int i = c; i <= n + 1; i ++ )
	swap(a[t][i], a[r][i]);//交换第r行与第t行
for(int i = n; i >= c; i ++ )
	a[r][i] /= a[r][c];//将第r行首非零数字跟新为1

for(int i = r + 1; i <= n; i ++ )
	if(fabs(a[i][c]) > eps) // eps 表示一个很小的值,因为c++浮点数存储原因,不能直接判断是否为零
		for(int j = n; j >= c; j -- )
			a[i][j] -= a[i][c] * a[r][j];

当跟新到最后一行时,再依次计算x的值并返回上一行进行计算。在这里插入图片描述

for(int i = n - 1; i >= 1; i -- )
	for(int j = i + 1; j <= n; j ++ )
		a[i][n + 1] -= a[i][j] * a[j][n + 1];

三、代码展示

#include <iostream>
#include <algorithm>
#include <cstring>
#include <cmath>
using namespace std;

const int N = 110;
const double eps = 1e-9;
double a[N][N];
int n;

int gauss(){
	int r, c;
	for(r = 1, c = 1; c <= n; c ++ ){
		int t = r;
		for(int i = r + 1; i <= n; i ++ )
			if(fabs(a[i][c]) > fabs(a[t][c]))t = c;
		
		if(fabs(a[t][c]) < eps)continue;
		
		for(int i = c; i <= n + 1; i ++ )swap(a[r][i], a[t][i]);
		for(int i = n + 1; i >= c; i -- )a[r][i] /= a[r][c];
		
		for(int i = r + 1; i <= n; i ++ )
			if(fabs(a[i][c]) > eps)
				for(int j = n + 1; j >= c; j -- )
					a[i][j] -= a[i][c] * a[r][j];
		r ++ ;
	}
	if(r <= n){
		for(int i = r; i <= n ; i ++ )
			if(fabs(a[r][n + 1]) > eps)return 1;
		return 2;
	}
	for(int i = n - 1; i >= 1; i -- )
		for(int j = i + 1; j <= n; j ++ )
			a[i][n + 1] -= a[i][j] * a[j][n + 1];
	return 0;
}

int main()
{
	cin >> n;
	for(int i = 1; i <= n; i ++ )
		for(int j = 1; j <= n + 1; j ++ )cin >> a[i][j];
	int t = gauss();
	if(t == 0)
		for(int i = 1; i <= n; i ++ )printf("%.2lf\n", a[i][n + 1]);
	else if(t == 1)puts("无解");
	else puts("有无穷多组解");
	return 0;
}

总结

敲代码时要理清思路,知道每一步的理由,多在草稿纸上演算;一起加油进步。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值