和求解行列式的值类似,当某一列的常数项全为0时,方程组无解或有无穷多解,此时退出程序;否则将列主元下面的元素逐个消去,直至循环结束。要注意的是为了保持数值的稳定性(精度),每次选取的列主元的系数都是该列绝对值最大的那个。
#include <cstdio>
#include <cmath>
#define MAXN 100
#define eps 1e-9
int gauss_elimination(int n,double a[][MAXN],double b[]){
int i,j,k,row;
double maxp,t;
for(k=0;k<n;k++){//行标+列标
for(maxp=0,i=k;i<n;i++)//行标
if (fabs(a[i][k])>fabs(maxp))//选取绝对值最大的主元素,保持数值稳定性
maxp=a[row=i][k];
if(fabs(maxp)<eps) return 0;
if(row!=k){
for(j=k;j<n;j++)
t=a[k][j],a[k][j]=a[row][j],a[row][j]=t;
t=b[k],b[k]=b[row],b[row]=t;
}
for(j=k+1;j<n;j++)//列标
for(a[k][j]/=maxp,i=k+1;i<n;i++)//行标
a[i][j]-=a[i][k]*a[k][j];
for(b[k]/=maxp,i=k+1;i<n;i++)//行标
b[i]-=b[k]*a[i][k];
}
for(i=n-1;i>=0;i--)
for(j=i+1;j<n;j++)
b[i]-=a[i][j]*b[j];
return 1;
}
int main(){
int i,j,n;
double a[MAXN][MAXN],b[MAXN];
while(scanf("%d",&n),n){
for(i=0;i<n;i++){
for(j=0;j<n;j++)
scanf("%lf",&a[i][j]);
scanf("%lf",&b[i]);
}
if(gauss_elimination(n,a,b))
for(i=0;i<n;i++)
printf("x%d : %.2lf\n",i+1,b[i]);
else
puts("Uncertain");
}
return 0;
}