高斯消元的过程
敲代码的注意事项:
1.for循环中的”++”和”- -“符号要应情况而选择,否则及容易打错,进而出现一些非常难找到的bug
2.doule和int的类型需要注意,例如输入输出过程,和定义过程
3.return的类型.
4.欢迎各位拿出自己宝贵的经验,分享容易出现的错误QWQ
#include<iostream>
#include<algorithm>
#include<cmath>
using namespace std;
const int N=110;
const double egs=1e-6;
double a[N][N];
int n;
int gause()
{
int r,c;//r表示当前所在的行数,c表示当前所指向的列数
for(r=0,c=0;c<n;c++)//进行n次循环,将矩阵化为三角的形式
{
int t=r;
for(int i=r;i<n;i++)
if(fabs(a[t][c])<fabs(a[i][c]))
t=i;
//寻找最大的数值是因为可以避免系数变得太大,精度较高.
if(fabs(a[t][c])<egs) continue;//如果最大值是零,便可以直接跳过了
//之所以要小于1e-6,是因为c++浮点数的一种弊端,所以小于egs时,可以近似的看作是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];
//将当前第c位的值初始化为1,当然其他数也同样需要除以第c位,之所以从第n位开始,是为了不覆盖掉第c位的值
for(int i=r+1;i<n;i++)
if(fabs(a[i][c])>egs)//如果当前行数为零,说明不用进行削为零的操作
for(int j=n;j>=c;j--)
a[i][j]-=a[i][c]*a[r][j];
r++;
}
if(r<n)
{
for(int i=r;i<n;i++)
if(a[i][n]>egs)
return 2;//无解
/*
如果当前列的绝对值最大的值是0,那么r还继续停留,不转到下一行,但c却转至下一行,
由于循环过程中会进行消元操作,所以循环到该列时,下面所有行的c列就会被消成零.
假设该列只有零的情况出现一次的话,那么r最终会循环到n-2行,而c却循环到了第n-1列,
因为循环过程中的消元,所以第n-1行的所有数都会被消成零.如果此时d不为零的话,矛盾,无解;
如果为零的话,那么就会有无数组解.一列都是零的情况出现两次,三次,甚至更多次都是同理.
*/
return 1;//无数解
}
//将未知数求解出来
for(int i=n-1;i>=0;i--)
for(int j=i+1;j<n;j++)
a[i][n]-=a[j][n]*a[i][j];
/*
只要保留第i行第i列的系数即可,所以从第i+1行开始一直消到第n行,
因为只要结果,所以可以只消第i行第n+1列的数(b);
*/
return 0;//有唯一解
}
int main()
{
cin>>n;
for(int i=0;i<n;i++)
for(int j=0;j<=n;j++)
scanf("%lf",&a[i][j]);
int t=gause();
if(t==0)
{
for(int i=0;i<n;i++) printf("%.2lf\n",a[i][n]);
}
else if(t==1) printf("Infinite group solutions");
else printf("No solution");
return 0;
}
好吧,竟然没有人发现错误,是13/4,而不是15/4
(偏离关注点wuli ~~ :egs指的 eps,Epsilon 么)const double egs=1e-6;或许是
const double eps=1e-6
感谢dalao让麻瓜理解了膜法
hhahah
egs应该写作eps哦qwq~(源于epsilon,这个希腊字母在数学上通常表示“无穷小”)
//将未知数求解出来
for(int i=n-1;i>=0;i–)//i,j表示’行’的同时也表示’列’
for(int j=i+1;j<n;j++)
a[i][n]-=a[j][n]*a[i][j];
大佬这个怎么算的
那里打错了,i表示的是行,j表示的是列
这一步是还原方程组,例如图中的还原方程
1 0.5 -1.5 -4.5
0 1 1/3 -1
0 0 1 3
到还原第二行的步骤
即将
0 1 1/3 -1
转变为
0 1 0 b
如果要将其消成这样,那么就必须把1/3的系数消掉
所以将第三行可以转变为
0 0 1/3 1
再用第二行减去第三行
即变为
0 1 0 -2 –>x2=-2;
消去第一行也是同理,
只要保留第1行第1列的结果,所以只要消去第2列第3列的系数,经过消元后就可以得出结果了
因为第i行中1的坐标是第i行第i列,而第二行中由于经过前面的消元,
所以只有第i列后面的才有系数,所以j=i+1(从后面列开始消,一直消到第n列)因为题中只要得出结果
所以第二行中只要最后面的结果消去就行
即a[i][n]-=a[j][n]*a[i][j];
谢谢大佬指教,加油!
嗯,听懂了就好,加油!!!
现在题解有点问题了,就是可能在判断无限解,与无解处,a i n可能小于零导致本应无解,变成了无限解,加一个fabs即可
# $\text{写的很好,但是是错的!}$
有地方要改,有问题,不信你们提交
送楼主一杯红茶
大佬好像有个地方不对,函数最后判断是否为0那里应该加一个fabs,要不然会报错的
懂了%%%%
感谢大佬让我这个高数渣看懂理解了www
tql
求绝对值是求某行和最大值还是说某一个数的最大值?
这个最好
写的太好了
gause…
牛逼
大佬,您的题解写得真的很好很棒,必须顶一个^v^~~。
写的很清楚
思路清晰 字好看 呜呜呜 爱了
QAQ
谢谢夸奖