高斯消元求线性方程组

高斯消元

给定一个线性方程组,对其求解

{a11x+a12x2++a1nxn=b1a21x+a22x2++a2nxn=b2am1x+am2x2++ammxn=bm

何为高斯消元

数学上,高斯消元法(或译:高斯消去法),是线性代数规划中的一个算法,可用来为线性方程组求解。但其算法十分复杂,不常用于加减消元法,求出矩阵的秩,以及求出可逆方阵的逆矩阵。不过,如果有过百万条等式时,这个算法会十分省时。一些极大的方程组通常会用迭代法以及花式消元来解决。当用于一个矩阵时,高斯消元法会产生出一个“行梯阵式”。高斯消元法可以用在电脑中来解决数千条等式及未知数。亦有一些方法特地用来解决一些有特别排列的系数的方程组

高斯消元法思想概念

德国数学家高斯对消元法进行了思考分析,得出了如下结论:

  1. 在消元法中,参与计算和发生改变的是方程中各变量的系数;
  2. 各变量并未参与计算,且没有发生改变;
  3. 可以利用系数的位置表示变量,从而省略变量;
  4. 在计算中将变量简化省略,方程的解不变。

高斯在这些结论的基础上,提出了高斯消元法,首先将方程的增广矩阵利用行初等变换化为行最简形,然后以线性无关为准则对自由未知量赋值,最后列出表达方程组通解。


我们可以通过高斯消元法可在 n3复杂度下求出线性方程的解

增广矩阵
所谓增广矩阵,即为方程组系数矩阵A 与常数列b 的并生成的新矩阵,即 ,增广矩阵行初等变换化为行最简形,即是利用了高斯消元法的思想理念,省略了变量而用变量的系数位置表示变量,增广矩阵中用竖线隔开了系数矩阵和常数列,代表了等于符号

对于

{a11x+a12x2++a1nxn=b1a21x+a22x2++a2nxn=b2am1x+am2x2++ammxn=bm

(a11a12b1a21a22b2a31a32b3a41a42b4)

增广矩阵


高斯消元的核心步骤

  1. 把某行乘以一个非0的数
  2. 交换2行的位置
  3. 把某行的若干倍加到另一行上

我们把这3类操作称为初等行列变化
高斯消元通过一个通用的形式,把我们的方程变为**“阶梯形矩阵”*

{a11x+a12x2++a1nxn=b1a22x2++a2nxn=b2+ammxn=bm

阶梯不一定都是这样的,因此我们有
对于

  1. 完美阶梯型,就会有唯一解
  2. 不完美阶梯型
    3. 若有方程0=d无解
    4. 若有方程0=0有无穷多组解

高斯消元算法步骤

  1. 枚举每一列c,找到当前一列,一个绝对值最大的一行
  2. 将该行c换到最上面一行(未确定阶梯型的行,并不是第一行)
  3. 将该行第一个系数变成1,方程两边同除系数
  4. 将当前列c下面所有行的系数都消为0【通过3操作】
  5. 在枚举c+1继续迭代

代码如下

#include <cstdio>
#include <algorithm>
#include <iostream>
#include <cmath>

using namespace  std;
const int N = 110;
const double esp = 1e-6;
int n;
double a[N][N];


int gauss()
{
    int c;//列
    int r;//行
    for(c = 0,r = 0; c < n ;c ++)
    {
        int t = r;
        for(int i = r ; i < n ; i ++)
        if(fabs(a[i][c]) > fabs(a[t][c]))
        t = i;//找到绝对值最大的一行
        
        if(fabs(a[t][c]) < esp)continue;
        /*如果当前这一列绝对值最大为0则
        */
        
        for(int i = c ; i <= n ; i ++ )swap(a[t][i],a[r][i]);//把当前一行换到最上面
        for(int i = n ;i >= c ; i--)a[r][i] /=a[r][c];
		/*
		 把当前这一行的第一个数,变成 1, 方程两边同时除以 第一个数,
		必须要倒着算,不然第一个数直接变1,系数就被篡改,后面的数字没法算
		*/
        
        for(int i = r + 1; i < n ;i ++)
        if(fabs(a[i][c]) > esp)//已经是 0就没必要操作了
            for(int j = n; j >= c ;j --)// 把当前列下面的所有数,全部消成 0
                a[i][j] -= a[r][j] * a[i][c];//把第一行第一个数变成0 
        r++;//这行工作做完了继续下一行
        
    }
    
    
        
    if(r < n)//说明剩下方程的个数是小于 n 的,说明不是唯一解,判断是无解还是无穷多解
    {// 因为已经是阶梯型,所以 r ~ n-1 的值应该都为 0
        for(int i = r;i < n ; i ++ )
        if(fabs(a[i][n]) > esp)
            return 2;//无解
        return 1;//无限解
        
    }
    for(int i = n - 1 ; i >= 0 ; i --)//用最后一列减去除了每一列xi之外的所有其他数
        for(int j = i + 1 ; j <= n ; j ++ )
        a[i][n] -= a[i][j] * a[j][n];
        
    return 0;//有唯一解
    
}


int main()
{
    scanf("%d",&n);
    for(int i = 0 ; i < n ; i ++ )
        for(int j = 0 ; j < n + 1 ; j ++ )
        scanf("%lf",&a[i][j]);
        
    int t = gauss();
    if(t == 0 )
    {
        for(int i = 0; i < n ; i ++ )printf("%.2lf\n",a[i][n]);
    }
    else if(t == 1)puts("Infinite group solutions");
    else puts("No solution");
    
}
posted @   Erfu  阅读(223)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 单线程的Redis速度为什么快?
· SQL Server 2025 AI相关能力初探
· AI编程工具终极对决:字节Trae VS Cursor,谁才是开发者新宠?
· 展开说说关于C#中ORM框架的用法!
点击右上角即可分享
微信分享提示