高斯人物介绍
首先让我们来了解一下这位伟大的数学家高斯:传送门
他的一生中有许多成就比如发明了高斯消元也就是我们要讲的内容,还有小学学习的等差数列也同样出自他手,所以他也被誉为“数学王子”。
高斯消元法基本介绍
首先大家可以看一看高斯消元法的基本介绍,之后会给大家讲一下我的理解:传送门
首先我认为高斯消元法就是一个能够解决n元一次方程组问题的方法,简单来说,比如下面这个例子
高斯消元的方法
我们选定x为主元,那么我们的任务就是要拿第一个式子中的x把下面式子中的x全部消掉以此来达到消元的目的
我们可以先拿第二个式子减去两倍的第一个式子,结果就会变成这样
然后我们再拿第三个式子减去三倍的第一个式子,这时候结果就会变成这样
这时候我们就已经达到目的把x全部消掉了
那么接下来我们就可以接着把y视为主元,把所有y都消掉
这时候我们发现只剩下z一个未知数轻松的解得z的值后再带入前两个方程就可以解出x和y了
这就是高斯消元法的方法
抽象高斯消元法
这时候你可能会问拿这样的确可以解决n元一次方程但怎么才能将它应用到实际的c编程当中呢,别急听我慢慢道来
首先我们可以结合一些线性代数的知识(ps:我也刚学一点点)
我们可以把方程组中未知数的系数和方程组的各个方程的结果抽象成一个个矩阵,就像这样
上图就是上文中方程组对应的矩阵
这时候我们就可以对这个矩阵做和上面的方程组做差不多的操作
这时候也可以达到一样的效果求出x,y,z三个未知数
这时候我们就可以把这个方法应用到代码当中了
代码详解
这里有一道模版题大家可以做一做:高斯消元模版题目
在这之前还有一个要注意的点提醒一下大家,就是为了避免编程中的精度损失,每次在找主元时要对应绝对值最大的方程来消其他方程中对应的未知数
话不多说,我这边直接上代码,解释啥的都在代码里边了
#include<bits/stdc++.h>
using namespace std;
const int N=110;
double a[N][N],eps=pow(10,-8);
// a[i][j]表示第j列对应的未知数在第i行的系数,
//eps就是为了避免精度误差如果最大的绝对值都接近于0的话
//直接判无解
int n;
bool flag=true;//是否有解
void gsxy(){
for (int i=1;i<=n;i++){//不断消元选择第i行i列的未知数作为主元
int pos=i;
for (int j=i+1;j<=n;j++){
if (fabs(a[j][i])>fabs(a[pos][i])) pos=j;
//选择对应主元绝对值最大的方程来消元
}
if (pos!=i){//作为主元所在的方程换到当前方程所在位置
for (int j=1;j<=n+1;j++){
swap(a[i][j],a[pos][j]);
}
}
if (fabs(a[i][i])<eps){//如果最大的绝对值都接近于0的话无解
cout<<"No Solution";
flag=false;
break;
}
for (int j=1;j<=n;j++){//消元,从1到n的目的是不用带回去算未知数的值直接把结果与剩下的系数相除
if (j!=i){
double tm=a[j][i]/a[i][i];//几倍
for (int k=1;k<=n+1;k++){
a[j][k]-=a[i][k]*tm;//每个对应的未知数相减
}
}
}
}
for (int i=1;i<=n;i++){//将结果与系数相除求得未知数的值
a[i][n+1]/=a[i][i];
}
}
int main(){
cin>>n;
for (int i=1;i<=n;i++){
for (int j=1;j<=n+1;j++){
cin>>a[i][j];
}
}
gsxy();
if (!flag) return 0;
for (int i=1;i<=n;i++){
printf("%.2lf\n",a[i][n+1]);//两位小数输出
}
return 0;
}
好了谢谢大家这篇文章就到这里结束了,大家轻喷我这个小蒟蒻