ページ 1 / 1
置き換えただけで誤った計算結果がでます。
Posted: 2018年8月02日(木) 23:44
by carnage0216
コード:
/*********************************************
* 連立方程式の解法 ( ガウスの消去法 )
*********************************************/
#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];
}
なぜなのかわかりません。どうか一緒に考えていただけないでしょうか?
Re: 置き換えただけで誤った計算結果がでます。
Posted: 2018年8月02日(木) 23:55
by box
ここで、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から引いています。そりゃ結果が違うのは当たり前です。
Re: 置き換えただけで誤った計算結果がでます。
Posted: 2018年8月03日(金) 00:47
by box
こうすればいいと思います。試していませんが。
コード:
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;
}
Re: 置き換えただけで誤った計算結果がでます。
Posted: 2018年8月03日(金) 01:56
by box
よく見てみたら、
ここと
コード:
d = a[i][N]/ a[i][i];
ここで使っている演算子が違っていますが(/= と /)本当はどっちにしたいんでしょうか。
いずれにしても、「置き換えただけ」という状態ではないので、
結果が違うのは当然かも。
Re: 置き換えただけで誤った計算結果がでます。
Posted: 2018年8月03日(金) 06:26
by かずま
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: 置き換えただけで誤った計算結果がでます。
Posted: 2018年8月03日(金) 06:36
by かずま
かずま さんが書きました: ↑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] も元と同じではありません。