高斯消元解方程组学习笔记

以下是正经的搞死小圆学习笔记!


---
数学课上,小圆遇到了一道六元一次方程组的题。颓废的小圆并不想做这道题,作为代课数学老师你决定搞死...不是,帮小圆解答这道题。请你设计程序解任意n元1次方程组。n<=100

【分析】

高斯消元隆重登场。

让我们先来替小圆模拟一下一个三元一次方程的解法(瞎写的,可能系数略恶心)
```math
3x+2y+4z=19   \ \ \ \  (1)

x-y+z=2 \ \ \ \ \ \ \ \ \ \ \ \ (2)

2x+y-3z=-5 \ \ \ \ \ (3)
```
回想小学高年级学到的解方程方法,我们可以通过联立方程消元,从而变成解一元一次方程的问题。

不妨先以(1)为未知数x的基准:
```math
x+ \frac{2}{3}y+\frac{4}{3}=\frac{19}{3} \ \ \   (1)'
```
对于(2)(3),需要在x与基准相同的情况下进行两式相减。一般来说,我们选择用x系数为1的(1)'来“凑”其他待消项的x的系数。

```math
(-1-\frac{2}{3})y+(1-\frac{3}{4}z)=(2-\frac{19}{3})z

→-\frac{5}{3}y-\frac{1}{3}z=-\frac{13}{3} \ \ \ (2)'
```
如此这般,最终消去y,得到z=1

下一步重要的操作是回代,本质是代入消元。

需要注意的是,在刚刚我们用(1)'消去其他方程中的x之后,(1)'就没有再次使用了,而且(1)'中x的系数为1。

遵循同样的方法,我们发现每个方程留下的最后形式,是用它消去的未知数的系数为1的情况,且该方程中的未知数只有这个数及其之后被消的数。

所以,我们回代时只需要用等号右边减去已求的所有数*它们的系数即可。

由于z是第一个被求出来的数,可以发现,回代需要依照倒序。

*考虑几个特殊情况:

1、解方程过程中发现当前未知数的系数在现在及之后的所有方程都为0——也就是说,这个未知数可以取任何值。输出"No Solution"(不存在唯一解)
即可。

2、我们希望关于未知数i的基准是剩余所有方程中i的系数绝对值最大的一个,为了保证答案的精准度。证明戳→[dalao](https://pks-loving.blog.luogu.org/p3389-mu-ban-gao-si-xiao-yuan-fa)

3、想清楚哪些地方应该用double,哪里应该与eps比较(嘤嘤嘤

最后贴代码~
```
#include<cstdio>
#include<iostream>
#include<algorithm>
#include<cmath>
using namespace std;
#define MAXN 105
#define eps 1e-7
double map[MAXN][MAXN],ans[MAXN];
//map存方程,ans存未知数的解
int n;
bool work(){
    for(int i=1;i<=n;i++){
        //以下是挑选绝对值最大的系数的过程
        int r=i;
        for(int j=i+1;j<=n;j++){
            if(fabs(map[j][i])>fabs(map[r][i]))
              r=j;
        }
        //情况1.最大都是0???
        if(fabs(map[r][i])<eps)
            return false;
            //无数组解
        if(r!=i)//需要交换
          swap(map[i],map[r]);
        double tmp=map[i][i];
                
        //以下是消元过程
        for(int j=i;j<=n+1;j++){//将基准方程中最前未知数系数化为1
            map[i][j]/=tmp;
        }

        for(int j=i+1;j<=n;j++){//其他方程消元
            tmp=map[j][i];
            for(int k=i;k<=n+1;k++)
              map[j][k]-=tmp*map[i][k];
        }
    }
    
    //以下是回代过程
    ans[n]=map[n][n+1];
    for(int i=n-1;i>=1;i--){
        ans[i]=map[i][n+1];
        for(int j=i+1;j<=n;j++)
          ans[i]-=(ans[j]*map[i][j]);
    }
    return true;
    //成功求出所有未知数
}

void print(){
    for(int i=1;i<=n;i++)
      printf("%.2lf\n",ans[i]);
}

int main(){
    scanf("%d",&n);
    for(int i=1;i<=n;i++)
      for(int j=1;j<=n+1;j++)
        scanf("%lf",&map[i][j]);
        
    if(!work())
          cout<<"No Solution"<<endl;
    else
        print();
    return 0;
}
```

### 使用 MATLAB 实现高斯消元法线性方程组 在 MATLAB 中实现高斯消元法决线性方程组主要依赖于矩阵的操作。具体来说,可以通过构建增广矩阵并对其进行行变换以化简成上三角形矩阵或简化行阶梯形式。 对于具体的实施过程,在 MATLAB 中可以编写如下函数来进行高斯消: ```matlab function x = gaussElimination(A, b) % A 是系数矩阵,b 是右侧向量 n = length(b); Ab = [A b]; % 构建增广矩阵 Ab for i = 1:n-1 for j = i+1:n factor = Ab(j,i)/Ab(i,i); % 计算乘数因子 Ab(j,:) = Ab(j,:) - factor * Ab(i,:); % 行变换操作 end end x = zeros(n,1); if n>0 && all(abs(diag(Ab(:,1:end-1))) ~= 0) % 判断是否为奇异矩阵 x(n) = Ab(n,n+1)/Ab(n,n); % 初始化最后一个变量 for k=n-1:-1:1 x(k) = (Ab(k,end)-Ab(k,1:end-1)*x)/(Ab(k,k)); % 后代入其他变量 end else error('The matrix is singular or nearly singular'); end ``` 上述代码定义了一个名为 `gaussElimination` 的函数用于执行高斯消算法[^1]。该函数接收两个参数作为输入:一个是代表线性系统的系数矩阵 \(A\);另一个是常数项组成的列向量 \(\mathbf{b}\),最终返回的是未知数构成的向量 \(\mathbf{x}\)[^2]。 为了验证这个方法的有效性和准确性,考虑一个简单的例子: 假设有一个三阶线性方程组 Ax=b 如下所示: \[ \begin{cases} 2x_1 + 3x_2 - x_3 &=& 7 \\ 4x_1 - 2x_2 + 5x_3 &=& 8\\ -2x_1 + 6x_2 + 9x_3 &=& 9 \end{cases} \] 对应的MATLAB命令将是这样的: ```matlab A = [2 3 -1; 4 -2 5; -2 6 9]; b = [7; 8; 9]; solution = gaussElimination(A,b) disp(solution); ``` 这段程序会调用之前编写的 `gaussElimination()` 函数,并打印出所获得的结果向量 solution[^3]。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值