置き換えただけで誤った計算結果がでます。

フォーラム(掲示板)ルール
フォーラム(掲示板)ルールはこちら  ※コードを貼り付ける場合は [code][/code] で囲って下さい。詳しくはこちら
carnage0216
記事: 20
登録日時: 6年前

置き換えただけで誤った計算結果がでます。

#1

投稿記事 by carnage0216 » 5年前

コード:

/*********************************************
 * 連立方程式の解法 ( ガウスの消去法 )
 *********************************************/
#include <iostream>  // for cout
#include <stdio.h>   // for printf()

// 元の数定義
#define N 4  // 3

using namespace std;

/*
 * 計算クラス
 */
class Calc
{
    double a[N][N + 1];

    // 各種変数
    double d;     // ダミー
    int i, j, k;  // LOOP インデックス

    public:
        // 連立方程式を解く(ガウスの消去法)
        void calcGaussElimination();
};

/*
 * 連立方程式を解く(ガウスの消去法)
 */
void Calc::calcGaussElimination()
{
    // 係数
    static double a[N][N + 1] = {
        //{ 2.0, -3.0,  1.0,  5.0},
        //{ 1.0,  1.0, -1.0,  2.0},
        //{ 3.0,  5.0, -7.0,  0.0}
        { 1.0, -2.0,  3.0, -4.0,  5.0},
        {-2.0,  5.0,  8.0, -3.0,  9.0},
        { 5.0,  4.0,  7.0,  1.0, -1.0},
        { 9.0,  7.0,  3.0,  5.0,  4.0}
    };

    // 元の連立方程式をコンソール出力
    for (i = 0; i < N; i++) {
        for (j = 0; j < N; j++)
            printf("%+fx%d ", a[i][j], j + 1);
        printf("= %+f\n", a[i][N]);
    }

    // 前進消去
    for (k = 0; k < N -1; k++) {
        for (i = k + 1; i < N; i++) {
            d = a[i][k] / a[k][k];
            for (j = k + 1; j <= N; j++)
                a[i][j] -= a[k][j] * d;
        }
    }

    // 後退代入
    for (i = N - 1; i >= 0; i--) {
        d = a[i][N];
        for (j = i + 1; j < N; j++)
            d -= a[i][j] * a[j][N];
        a[i][N] = d / a[i][i];
    }

    // 結果出力
    for (k = 0; k < N; k++)
        printf("x%d = %f\n", k + 1, a[k][N]);
}

/*
 * メイン処理
 */
int main()
{
    try
    {
        // 計算クラスインスタンス化
        Calc objCalc;

        // 連立方程式を解く(ガウスの消去法)
        objCalc.calcGaussElimination();
    }
    catch (...) {
        cout << "例外発生!" << endl;
        return -1;
    }

    // 正常終了
    return 0;
}
が全体のコードです。
このコードの

コード:

for (i = N - 1; i >= 0; i--) {
        d = a[i][N];
        for (j = i + 1; j < N; j++)
            d -= a[i][j] * a[j][N];
        a[i][N] = d / a[i][i];
    }
の部分を以下のように書き換えました。

コード:

for (i = N - 1; i >= 0; i--) {
        a[i][N] /= a[i][i];
        for (j = i + 1; j < N; j++)
            a[i][N] -= a[i][j] * a[j][N] / a[i][i];
    }
そして、以下のように自分に見やすいようにa[N]をdと置き換えたところ正しい計算結果ではなく間違った計算結果が出ました。

コード:

for (i = N - 1; i >= 0; i--) {
  d = a[i][N]/ a[i][i];
    for (j = i + 1; j < N; j++)
    a[i][N] = d - a[i][j] * a[j][N] / a[i][i];
}
なぜなのかわかりません。どうか一緒に考えていただけないでしょうか?

box
記事: 2002
登録日時: 13年前

Re: 置き換えただけで誤った計算結果がでます。

#2

投稿記事 by box » 5年前

コード:

        a[i][N] /= a[i][i];
ここで、a[N]を初期化して、

コード:

        for (j = i + 1; j < N; j++)
            a[i][N] -= a[i][j] * a[j][N] / a[i][i];
ここで、初期化してあったa[N]自身から引いています。
それに対して、

コード:

  d = a[i][N]/ a[i][i];
    for (j = i + 1; j < N; j++)
    a[i][N] = d - a[i][j] * a[j][N] / a[i][i];
こっちでは、a[N]ではなくてdから引いています。そりゃ結果が違うのは当たり前です。
バグのないプログラムはない。
プログラムは思ったとおりには動かない。書いたとおりに動く。

box
記事: 2002
登録日時: 13年前

Re: 置き換えただけで誤った計算結果がでます。

#3

投稿記事 by box » 5年前

こうすればいいと思います。試していませんが。

コード:

for (i = N - 1; i >= 0; i--) {
    d = a[i][N] / a[i][i];
    for (j = i + 1; j < N; j++)
        d -= [i][j] * a[j][N] / a[i][i];
    a[i][N] = d;
}
バグのないプログラムはない。
プログラムは思ったとおりには動かない。書いたとおりに動く。

box
記事: 2002
登録日時: 13年前

Re: 置き換えただけで誤った計算結果がでます。

#4

投稿記事 by box » 5年前

よく見てみたら、

コード:

        a[i][N] /= a[i][i];
ここと

コード:

  d = a[i][N]/ a[i][i];
ここで使っている演算子が違っていますが(/= と /)本当はどっちにしたいんでしょうか。
いずれにしても、「置き換えただけ」という状態ではないので、
結果が違うのは当然かも。
バグのないプログラムはない。
プログラムは思ったとおりには動かない。書いたとおりに動く。

かずま

Re: 置き換えただけで誤った計算結果がでます。

#5

投稿記事 by かずま » 5年前

N = 3 の場合を考ると、i は 2, 1, 0 と変化します。
i = 2 の時、j = 3 から始まるので j の for文の中身は実行されません。
i = 1 の時、j = 2 です。
i = 0 の時、j は、1, 2 と変化します。

コード:

    for (i = N - 1; i >= 0; i--) {
        d = a[i][N];
        for (j = i + 1; j < N; j++)
            d -= a[i][j] * a[j][N];
        a[i][N] = d / a[i][i];
    }
これは、書き換えると

コード:

    a[2][3] = (a[2][3]) / a[2][2];
    a[1][3] = (a[1][3] - a[1][2]*a[2][3]) / a[1][1];
    a[0][3] = (a[0][3] - a[0][1]*a[1][3] - a[0][2]*a[2][3]) / a[0]][0];
引き算を実行してから、割り算を実行しています。
次に

コード:

    for (i = N - 1; i >= 0; i--) {
        a[i][N] /= a[i][i];
        for (j = i + 1; j < N; j++)
            a[i][N] -= a[i][j] * a[j][N] / a[i][i];
    }
これは、書き換えると

コード:

    a[2][3] = a[2][3]/a[2][2];
    a[1][3] = a[1][3]/a[1][1] - a[1][2]*a[2][3]/a[1][1];
    a[0][3] = a[0][3]/a[0][0] - a[0][1]*a[1][3]/a[0][0] - a[0][2]*a[2][3]/a[0]][0];
割り算を先に実行してから、引き算を実行しています。

(6 - 2 - 3) / 7 = 6/7 - 2/7 - 3/7 のように、
これは同じ値になります。

コード:

    for (i = N - 1; i >= 0; i--) {
        d = a[i][N]/ a[i][i];
        for (j = i + 1; j < N; j++)
            a[i][N] = d - a[i][j] * a[j][N] / a[i][i];
    }
これは、書き換えると

コード:

    i = 2 の時
    a[2][3] は変化しない。(d = a[2][3] / a[2][2]; だけが実行される)

    i = 1, j = 2 の時
	a[1][3] = a[1][3]/a[1][1] - a[1][2]*a[2][3]/a[1][1]; (これだけが元と同じ)

    i = 0, j = 1 の時
	a[0][3] = a[0][3]/a[0][0] - a[1][1]*a[1][3]/a[0][0];
	i = 0, j = 2 の時、
	a[0][3] = a[0][3]/a[0][0] - a[1][2]*a[2][3]/a[0][0]; (a[0][3] を上書き)

かずま

Re: 置き換えただけで誤った計算結果がでます。

#6

投稿記事 by かずま » 5年前

かずま さんが書きました:
5年前
これは、書き換えると

コード:

    i = 2 の時
    a[2][3] は変化しない。(d = a[2][3] / a[2][2]; だけが実行される)

    i = 1, j = 2 の時
	a[1][3] = a[1][3]/a[1][1] - a[1][2]*a[2][3]/a[1][1]; (これだけが元と同じ)
訂正します。
a[2][3] が変化していないので、それを使って計算した
a[1][3] も元と同じではありません。

返信

“C言語何でも質問掲示板” へ戻る