しかし、n=9程度で使い物にならなくなってしまいました。
そこで、やっぱり基本のガウスの消去法を実装してみました。
ガウスの消去法 - Wikipedia
作ったコードがこちら。
#include
#include
#if 0
#define DO_TEST_PRINT
#endif
double** allocMatrix(int n) {
double** result;
int i;
/*列のメモリを確保*/
result=malloc(sizeof(double*)*n);
/*メモリ確保エラー*/
if(result==NULL)return NULL;
/*各行のメモリを確保*/
for(i=0;i=0;i--)free(result[i]);
free(result);
return NULL;
}
}
return result;
}
void freeMatrix(double** mat,int n) {
int i;
for(i=0;i=n) {
/*エラー*/
freeMatrix(mat2,n);
freeVector(vec2);
return 0;
}
/*交換*/
tempp=mat2[i];
mat2[i]=mat2[j];
mat2[j]=tempp;
tempd=vec2[i];
vec2[i]=vec2[j];
vec2[j]=tempd;
}
/*係数を1にする*/
for(j=i+1;j=0;i--) {
for(j=i-1;j>=0;j--) {
vec2[j]-=mat2[j][i]*vec2[i];
mat2[j][i]=0;
}
}
#ifdef DO_TEST_PRINT
/*テスト出力*/
puts("後退代入");
for(i=0;i<n;i++) {
for(j=0;j<n;j++) {
fprintf(stderr,"%7.1f",mat2[i][j]);
}
fprintf(stderr,"%7.1f\n",vec2[i]);
}
#endif
/*結果を代入*/
for(i=0;i<n;i++)result[i]=vec2[i];
/*コピーした方程式を開放*/
freeMatrix(mat2,n);
freeVector(vec2);
/*成功*/
return 1;
}
/*
使い方
まず、n元連立方程式を解く場合のnを整数で入力します。
次に、例えばn=3のとき、
一つの式がax+by+cz=dだとしたら、
a b c d
と入力します。
これをn回繰り返します。
すると、結果が最初の変数から順に表示されます。
この例だと
x
y
z
と表示されます。
入力のa、b、c、dと出力のx、y、zには具体的な実数が入ります。
*/
int main(void) {
int n;
double** mat;
double* vec;
double* result;
int i,j;
/*nの入力*/
scanf("%d",&n);
if(n<=0)return 1;
/*行列の確保*/
mat=allocMatrix(n);
if(mat==NULL)return 1;
/*ベクトルの確保*/
vec=allocVector(n);
if(vec==NULL) {
freeMatrix(mat,n);
return 1;
}
result=allocVector(n);
if(result==NULL) {
freeMatrix(mat,n);
freeVector(vec);
return 1;
}
/*値の入力*/
for(i=0;i<n;i++) {
for(j=0;j<n;j++) {
scanf("%lf",&mat[i][j]);
}
scanf("%lf",&vec[i]);
}
/*計算*/
if(solveHouteisiki(result,mat,vec,n)) {
/*結果の表示*/
for(i=0;i<n;i++) {
printf("%g\n",result[i]);
}
} else {
puts("error");
}
/*メモリの開放*/
freeMatrix(mat,n);
freeVector(vec);
freeVector(result);
/*正常終了*/
return 0;
}
20元連立方程式の正しい解を一瞬で出してくれました。
うん、やっぱ普通のアルゴリズムはすばらしい。
オフトピック
何がゼロ除算が怖いだよ。俺のバカ。