質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

ただいまの
回答率

89.12%

二つのプログラムに関してなぜ結果が異なるのでしょうか?

解決済

回答 5

投稿 編集

  • 評価
  • クリップ 2
  • VIEW 1,909

carnage0216

score 129

<環境>

  • windows10
  • visual studio 2017
/*********************************************
 * 連立方程式の解法 ( ガウスの消去法 )
 *********************************************/
#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--) {
        d = a[i][N];
        for (j = i + 1; j < N; j++)

        a[i][N] = d - a[i][j] * a[j][N] / a[i][i];
    }


と置いてビルドするといじっていない元のプログラムと同じ結果が出ると思ったのですが全く異なった結果が出ました。
いじる前の計算結果はこちらです。

+1.000000x1 -2.000000x2 +3.000000x3 -4.000000x4 = +5.000000
-2.000000x1 +5.000000x2 +8.000000x3 -3.000000x4 = +9.000000
+5.000000x1 +4.000000x2 +7.000000x3 +1.000000x4 = -1.000000
+9.000000x1 +7.000000x2 +3.000000x3 +5.000000x4 = +4.000000
x1 = 1.000000
x2 = 3.000000
x3 = -2.000000
x4 = -4.000000


いじった後の結果はこちらです。

+1.000000x1 -2.000000x2 +3.000000x3 -4.000000x4 = +5.000000
-2.000000x1 +5.000000x2 +8.000000x3 -3.000000x4 = +9.000000
+5.000000x1 +4.000000x2 +7.000000x3 +1.000000x4 = -1.000000
+9.000000x1 +7.000000x2 +3.000000x3 +5.000000x4 = +4.000000
x1 = 82.333333
x2 = 231.666667
x3 = -275.415033
x4 = 19.333333

正直なところなぜ結果が違うのかよくわかりませんでした。別に{}を付いてないので式を一つにまとめても同じ結果が出ると思っていました。

8/5 編集
dを使ってのプログラム

for (i = N - 2; i >= 0; i--) {
d = a[i][N]/ a[i][i];
a[i][N] =d*a[i][i];
for (j = N-1; j < N; j++)
a[i][N]=a[i][N] - a[i][j] * a[j][N] / a[i][i];
} 
  • 気になる質問をクリップする

    クリップした質問は、後からいつでもマイページで確認できます。

    またクリップした質問に回答があった際、通知やメールを受け取ることができます。

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 過去に投稿した質問と同じ内容の質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

回答 5

checkベストアンサー

+2

やるとしたらこう

    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];
    }

ただし、CPUの演算の中で割り算というのは一番遅い演算と言っても過言ではないので
(x+y+z) / w = x/w + y/w + z/w
という展開は無駄でしかない


追記

とりあえず、前回の計算式
a[i][N] = (a[i][N]-なにか) / a[i][i]を思い出す。
分配する
a[i][N] = a[i][N]/a[i][i] - なにか/a[i][i]
あとはそれに従ってプログラムに変換するだけ


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];
}

このfor文をi=0,N=3で展開すると

i = 0;
d = a[i][3] / a[i][i];
j = 1; a[i][N] = d - a[i][j]*a[j][N]/a[i][i];
j = 2; a[i][N] = d - a[i][j]*a[j][N]/a[i][i];

みたいな感じ
j=1の時の計算が丸ごと捨てられています。

投稿

編集

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2018/08/06 00:04

    2つの結果が違うのは当然です。プログラムの動作に明確な違いが見つかりますから。配列とforループを学んだ人なら理解すると思います。ところがこれだけ手間をかけて、理解できていないかもしれない・自信はない、、、というか理解できた様子が窺えません。未だに「d=...」で計算できないのかという未練を押しとどめようとしているようです。
    いつだったか、向いてないかもしれないと自問してたことがありましたね。君は向いてません。

    キャンセル

  • 2018/08/08 23:30 編集

    rubato6809

    rubato6809さん、解答ありがとうございます。
    >>君は向いてません。
    はっきり言っていただき本当にありがとうございます。僕は曖昧なものが理解できないので大変助かります。自分なりにやっと理解できてきましたが、やはり時間をこれだけかけてやっと理解できたところを考えると向いてないですね。追々このサイトからいなくなるかもしれませんが気を悪くしないでください。
    >>未だに「d=...」で計算できないのかという未練を押しとどめようとしているようです。
    それに関しては自分なりに完結させました。
    >>ところがこれだけ手間をかけて、理解できていないかもしれない・自信はない、、、というか理解できた様子が窺えません。
    やっと理解は出来ました。しかし、自信は持てません。ここまで助けてもらって何を自信にしていいかわかりません。一人じゃ何もできない僕に自信を持つこと自体無理な話です。

    キャンセル

  • 2018/08/09 00:32 編集

    d = a[i][N]/ a[i][i];でプログラムを作っているわけではありませんが、

    #include <iostream>
    #include <stdio.h>

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

    using namespace std;

    //double a[N][N+1];
    // 係数
    static double a[N][N + 1] = {
    { 1.0, 2.0, 8.0, 4.0},
    { 4.0, 3.0, 2.0, 12.0},
    { 1.0, 4.0, 2.0, 4.0},
    };


    int main()
    {
    double d;
    int i=2;

    d = a[i][N] / a[i][i]; //d = a[2][3] / a[2][2]
      a[i][N] = d - a[i][i] * a[i][N] / a[i][i];
    printf("%f\n", a[i][N]);


    a[i][N] = a[i][N] / a[i][i]; //d = a[2][3] / a[2][2]
         a[i][N] = a[i][N] - a[i][i] * a[i][N] / a[i][i];
    printf("%f\n", a[i][N]);

    return 0;
    }

    実行結果
    -2.000000
    0.000000
    より何が理解できていなかったのかを知りました。置き換えることで計算する過程が異なりことを知りました。
    私はプログラミングに向いていないかもしれませんが、食いついて学習していきrubato6809さんに認めてもらえるよう努力します。私は頭は悪い落ちこぼれですが、粘着質で諦めは悪い方なので今後ともよろしくお願いいたします。

    キャンセル

+2

連立方程式を解くプログラムを多元線形連立方程式にするには

え、なにやってんの
別サイトでわからなくってこのサイトに投稿
で、このサイトでわからなくって別サイトに投稿

人を振り回すのが好きなんですね。
編集前

for (int i = N - 1; i >= 0; i--) {
    d = a[i][N];
    for (int j = i + 1; j < N; j++) {
        d -= a[i][j] * a[j][N];
    }
    printf("(i)%d, %d\n", i, d);
    a[i][N] = d / a[i][i];
}


のループ処理で変数dがどのような値に変化しているか
理解できてないんじゃないですか。

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2018/08/02 15:55 編集

    計算が違ったのですね。
    はい、dがどのように変化するか理解できていないので計算を一から行います。

    キャンセル

+2

forとprintf()あたりを使って,

1
12
123
1234
12345
...

みたいなのを出力するプログラム書けますか?
おそらく,この辺からやっていった方が良いと思います.
(煽りとかじゃなく,きっと,その方がかえって近道だろうという意味で)

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

+1

計算順序が違うから。
4数をp,q,r,sとすると、
前者は(p-q*r)/sを、
後者はp-(q*r/s)を計算している。
後者はq*r/sが減算より先に処理されるため、前者と違う計算を行うことになる。

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2018/08/02 00:04

    わかりやすい回答どうもありがとうございます。
    なるほど、ではp/s-q*r/sと出来るように組んでみます。

    キャンセル

0

別に{}を付いてないので式を一つにまとめても同じ結果が出ると思っていました。

{ } が付いていないので、1つにまとめたら違う結果が出るに決まっているじゃないですか。

d -= a[i][j] * a[j][N];jのループの中で実行されて、a[i][N] = d / a[i][i];jのループが終わってから実行されます。

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2018/08/02 00:04

    解答どうもありがとうございます。

    キャンセル

15分調べてもわからないことは、teratailで質問しよう!

  • ただいまの回答率 89.12%
  • 質問をまとめることで、思考を整理して素早く解決
  • テンプレート機能で、簡単に質問をまとめられる