[C言語]ガウスの消去法を用いた掃き出し法のプログラムを組んでみた~準備編~[コード付き]

どうも、シュモクザメです。
今回は割とガッツリしたプログラムを組んでみます。


なお、今回は準備編です。
具体的に言うと問題生成の関数や中身を表示する関数を作ります。
ガウスの消去法(掃き出し法)自体の関数は完成編で扱うのでご了承ください。



どのように実装するかを考える

もちろん一番大事なのは掃き出し法の関数です。
これは(完成編)でしっかり作っていくことにします。

その際、行列はファイルに入れて扱うことにします。
なのでファイルの中身を読み取る関数が必要ですね。

また生成した問題をファイルに格納する関数も必要です。

その他諸々作ってしまいましょう



コードの実装


問題を生成してファイルに書き込む関数

まずこれから,

係数も定数項もすべて-1~1の間の値をランダムに持たせることにします。
一旦コードです

void Q(int N, char s[NMAX]){
    int i,j;
    FILE *fp;
    
    if((fp = fopen(s,"w"))==NULL)
        printf("ファイルを開けません\n");
    else{
        for(i=0; i<N; i++){
            for(j=0; j<N+1; j++){
                double r = 2*(double)(rand()/(double)RAND_MAX)-1;
                fprintf(fp,"%f ",r);
            }
            fprintf(fp,"\n");
        }
        fclose(fp);
    }
}

仮引数のNは、係数行列がN×Nであるという意味です。
char sは問題を書き込むファイルの名前です


ファイルのオープンはよくある形 if(fp=fopen) の形ですね
fopenはrモードで開きます


1つ目のforループの回数はNですが、
2つ目のforループの回数はN+1です。
これは定数項の部分が増えるからですね。


またループの最も内側ではfprintfを使って係数や定数項を開いたファイルに書き込んでいます。

このとき-1~1の範囲に乱数を収めるため、

 double r = 2*(double)(rand()/(double)RAND_MAX)-1;

このようにしています。

rand()/(double)RAND_MAXで0~1の範囲にして、
それを二倍して0~2、
そこから-1することで-1~1ということです。



問題が入ったファイルを読み込む関数

上の関数で作った問題を、
main関数で扱うために係数と定数項に分けてそれぞれ配列に格納する関数を作ります。

void SCAN(int N, double A[N][N], double B[N], char s[NMAX]){
    double b = 0;
    FILE *fp;
    
    
    if((fp = fopen(s,"r"))==NULL)
        printf("ファイルを開けません\n");
    else{
        for(int i=0; i<N; i++){
            double a[N];
            for(int j=0; j<N; j++){
                fscanf(fp,"%lf",&a[j]);
                A[i][j] = a[j];
            }
            fscanf(fp,"%lf",&b);
                  B[i] = b;
        }
        fclose(fp);
    }
}

仮引数のA[N][N]が係数行列が入る配列、
B[N]が定数項が入る配列で残りは上の関数と同じです。


fopenをwモードで開きます。


外側のforループは行を表してますね。N回まわります。

次にその内側ですが、
まずN回forループを回して係数をすべてfscanfで配列Aに書き込みます。
内側のループを抜けたあとは外側のループを抜けずに、一度fscanfを行います。

これでN+1列目に書かれている定数項を回収できるということです。
なのでここで回収する値は配列Bに書き込みます。



配列の中身を表示する関数

mainで中身を表示することが絶対あるので作ります。
2次元配列用と1次元配列用で分けます。

void SHOW_2(int N, double A[N][N]){
    int i, j;
    for(i=0; i<N; i++){
        for(j=0; j<N; j++){
            printf("%f ",A[i][j]);
        }
        printf("\n");
    }
}
void SHOW_1(int N, double B[N]){
    int i;
    for(i=0; i<N; i++){
        printf("%f\n",B[i]);
    }
}

これはそのままですね、



準備完了

これで諸々の関数ができました。

次回は計算そのものの関数を作っていきます。


ではまた、

syumokuzame

コメントを残す

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です

コメントする