2009-04-28

[C語言] 高斯消去法-特約化矩陣(RREF)


#include<stdio.h>
#include<stdlib.h>

/*高斯消去法 - 特約化矩陣*/
double **matrix_rref(double **matrix, int m, int n){
double zero=0.00000001;
double temp;

int x=0,y=0,j,i;
while(x<n && y<m){
// 如果列首為零,則找尋可以互換的列
while(x<n && matrix[y][x]<zero && matrix[y][x]>(-zero)){
j=y+1;
while(j<m && matrix[j][x]<zero && matrix[j][x]>(-zero)){j++;}

// 此行都為零,移至下一行
if(j >= m){ x++; continue; }

// 找到列首不為零的列,兩列互換
for(i=x; i<n; i++){
temp=matrix[j][i];
matrix[j][i]=matrix[y][i];
matrix[y][i]=temp;
}
// 互換結束跳出迴圈
break;
}
if(x>=n){ break; }

// 所有列值都除以列首,列首為(1)處理
for(i=n-1; i>x; i--){
matrix[y][i]/=matrix[y][x];
}
matrix[y][x]=1;

// 消去上下列
for(j=0; j<m; j++){
// 跳過選取的列
if(j == y){ continue; }

// 選取的列消去其他列
for(i=n-1; i>=x; i--){
matrix[j][i]-=matrix[y][i]*matrix[j][x];
}
}

x++; y++;
}
return matrix;
}



/*
input.txt
4 5
1 2 3 7 55
1 3 2 4 76
3 2 1 6 43
4 6 5 3 34
*/

/*主程式*/
int main(){
int m,n,i,j;
FILE *in;
// 開啟檔案
in=fopen("input.txt","r");

// 讀取 m,n 值
fscanf(in,"%d\n",&m);
fscanf(in,"%d\n",&n);

// 利用 malloc 配置二維空間 。
double **mar= (double**) malloc(m * sizeof(double*));
for (i=0; i<m; i++){
mar[i] = (double*) malloc(n * sizeof(double));
}

// 讀取矩陣
for(i=0;i<m;i++){
for(j=0;j<n;j++){
fscanf(in,"%lf",&mar[i][j]);
}
}

// 高斯消去法
mar=matrix_rref(mar,m,n);

// 列印結果
for(i=0;i<m;i++){
for(j=0;j<n;j++){
printf("%.2lf ",mar[i][j]);
}
printf("\n");
}

_getch();

return 0;
}

6 回應:

匿名 提到...

請問你的列首是對角線元素嗎?
1 0 1
0 1 1
1 0 0
的話 第一列與第二列都不用換
可是第三列卻要跟第一列換

胡忠晞 Jax 提到...

永遠只從下方找非零的列做交換
所以不會出現你說的狀況

林鈺書 提到...

您好:想請問
while(x(-zero))
為什麼要這樣使用
不直接使用
matrix[y][x]==0就好

林鈺書 提到...
作者已經移除這則留言。
胡忠晞 提到...

這是浮點數誤差的問題,一個例子:
float a = 10/2/5
//a => 1.00000000001

林鈺書 提到...

謝謝您的解惑!!