#2
by かずま » 5年前
carnage0216 さんが書きました: ↑5年前
例えば、k=0の時、i=0となります。d = a
[k] / a[k][k]よりjは1となり、 a[j] -= a[k][j] * dは a[j] -= a[0][1] * 1より、 a[j]は a[0][1]となるため-2と、、、何を行なっているのか悩んでしまい全く理解ができません。
コード:
[i] と書くと、イタリック体タグと解釈されて、
[i] は表示されず、以後、半角文字がすべて斜体になります。
[i] を表示したければ、御覧のように codeタグを使うなどの工夫が必要です。
コードをよく見てください。
k = 0 の時、i = 0 にはなりません。
i = k + 1 ですから、i = 1 となります。
コード:
d = a[i][k] / a[k][k] = a[1][0] / a[0][0] = -2
j = k + 1 = 1
a[i][j] -= a[k][j] * d より
a[1][1] = 1
a[1][2] = 14
a[1][3] = -11
プログラムの理解のために、j = k + 1 を j = k にすると
a[1][0] = 0
になることがわかります。
次のプログラムで確かめてください。
コード:
/*********************************************
* 連立方程式の解法 ( ガウスの消去法 )
*********************************************/
#include <iostream> // for cout
#include <cstdio> // for printf()
const int N = 4; // 元の数定義
using namespace std;
class Calc { // 計算クラス
public:
void calcGaussElimination(); // 連立方程式を解く(ガウスの消去法)
};
void print(int k, double d, double a[N][N+1]) // ★ デバッグプリント
{
printf("--- k = %d, d = %g ---\n", k, d);
for (int i = 0; i < N; i++) { // 元の連立方程式をコンソール出力
for (int j = 0; j < N; j++)
printf("%+8g ", a[i][j]);
printf("= %+8g\n", a[i][N]);
}
}
void Calc::calcGaussElimination() // 連立方程式を解く(ガウスの消去法)
{
static double a[N][N + 1] = { // 係数
{ 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 (int i = 0; i < N; i++) { // 元の連立方程式をコンソール出力
for (int j = 0; j < N; j++)
printf("%+f x%d ", a[i][j], j + 1);
printf("= %+f\n", a[i][N]);
}
cout << "[ 前進消去 ]\n";
for (int k = 0; k < N -1; k++) { // 前進消去
for (int i = k + 1; i < N; i++) {
double d = a[i][k] / a[k][k];
for (int j = k; j <= N; j++) // ★ k + 1 --> k
a[i][j] -= a[k][j] * d;
print(k, d, a); // ★
}
}
for (int i = N - 1; i >= 0; i--) { // 後退代入
double d = a[i][N];
for (int j = i + 1; j < N; j++)
d -= a[i][j] * a[j][N];
a[i][N] = d / a[i][i];
}
for (int 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; // 正常終了
}
実行結果
コード:
+1.000000 x1 -2.000000 x2 +3.000000 x3 -4.000000 x4 = +5.000000
-2.000000 x1 +5.000000 x2 +8.000000 x3 -3.000000 x4 = +9.000000
+5.000000 x1 +4.000000 x2 +7.000000 x3 +1.000000 x4 = -1.000000
+9.000000 x1 +7.000000 x2 +3.000000 x3 +5.000000 x4 = +4.000000
[ 前進消去 ]
--- k = 0, d = -2 ---
+1 -2 +3 -4 = +5
+0 +1 +14 -11 = +19
+5 +4 +7 +1 = -1
+9 +7 +3 +5 = +4
--- k = 0, d = 5 ---
+1 -2 +3 -4 = +5
+0 +1 +14 -11 = +19
+0 +14 -8 +21 = -26
+9 +7 +3 +5 = +4
--- k = 0, d = 9 ---
+1 -2 +3 -4 = +5
+0 +1 +14 -11 = +19
+0 +14 -8 +21 = -26
+0 +25 -24 +41 = -41
--- k = 1, d = 14 ---
+1 -2 +3 -4 = +5
+0 +1 +14 -11 = +19
+0 +0 -204 +175 = -292
+0 +25 -24 +41 = -41
--- k = 1, d = 25 ---
+1 -2 +3 -4 = +5
+0 +1 +14 -11 = +19
+0 +0 -204 +175 = -292
+0 +0 -374 +316 = -516
--- k = 2, d = 1.83333 ---
+1 -2 +3 -4 = +5
+0 +1 +14 -11 = +19
+0 +0 -204 +175 = -292
+0 +0 +0 -4.83333 = +19.3333
x1 = 1.000000
x2 = 3.000000
x3 = -2.000000
x4 = -4.000000
[quote=carnage0216 post_id=151195 time=1532449213 user_id=2683]
例えば、k=0の時、i=0となります。d = a[i][k] / a[k][k]よりjは1となり、 a[i][j] -= a[k][j] * dは a[i][j] -= a[0][1] * 1より、 a[i][j]は a[0][1]となるため-2と、、、何を行なっているのか悩んでしまい全く理解ができません。
[/quote]
[code]
[i] と書くと、イタリック体タグと解釈されて、
[i] は表示されず、以後、半角文字がすべて斜体になります。
[i] を表示したければ、御覧のように codeタグを使うなどの工夫が必要です。
[/code]
コードをよく見てください。
k = 0 の時、i = 0 にはなりません。
i = k + 1 ですから、i = 1 となります。
[code]
d = a[i][k] / a[k][k] = a[1][0] / a[0][0] = -2
j = k + 1 = 1
a[i][j] -= a[k][j] * d より
a[1][1] = 1
a[1][2] = 14
a[1][3] = -11
プログラムの理解のために、j = k + 1 を j = k にすると
a[1][0] = 0
になることがわかります。
[/code]
次のプログラムで確かめてください。
[code]
/*********************************************
* 連立方程式の解法 ( ガウスの消去法 )
*********************************************/
#include <iostream> // for cout
#include <cstdio> // for printf()
const int N = 4; // 元の数定義
using namespace std;
class Calc { // 計算クラス
public:
void calcGaussElimination(); // 連立方程式を解く(ガウスの消去法)
};
void print(int k, double d, double a[N][N+1]) // ★ デバッグプリント
{
printf("--- k = %d, d = %g ---\n", k, d);
for (int i = 0; i < N; i++) { // 元の連立方程式をコンソール出力
for (int j = 0; j < N; j++)
printf("%+8g ", a[i][j]);
printf("= %+8g\n", a[i][N]);
}
}
void Calc::calcGaussElimination() // 連立方程式を解く(ガウスの消去法)
{
static double a[N][N + 1] = { // 係数
{ 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 (int i = 0; i < N; i++) { // 元の連立方程式をコンソール出力
for (int j = 0; j < N; j++)
printf("%+f x%d ", a[i][j], j + 1);
printf("= %+f\n", a[i][N]);
}
cout << "[ 前進消去 ]\n";
for (int k = 0; k < N -1; k++) { // 前進消去
for (int i = k + 1; i < N; i++) {
double d = a[i][k] / a[k][k];
for (int j = k; j <= N; j++) // ★ k + 1 --> k
a[i][j] -= a[k][j] * d;
print(k, d, a); // ★
}
}
for (int i = N - 1; i >= 0; i--) { // 後退代入
double d = a[i][N];
for (int j = i + 1; j < N; j++)
d -= a[i][j] * a[j][N];
a[i][N] = d / a[i][i];
}
for (int 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; // 正常終了
}
[/code]
実行結果
[code]
+1.000000 x1 -2.000000 x2 +3.000000 x3 -4.000000 x4 = +5.000000
-2.000000 x1 +5.000000 x2 +8.000000 x3 -3.000000 x4 = +9.000000
+5.000000 x1 +4.000000 x2 +7.000000 x3 +1.000000 x4 = -1.000000
+9.000000 x1 +7.000000 x2 +3.000000 x3 +5.000000 x4 = +4.000000
[ 前進消去 ]
--- k = 0, d = -2 ---
+1 -2 +3 -4 = +5
+0 +1 +14 -11 = +19
+5 +4 +7 +1 = -1
+9 +7 +3 +5 = +4
--- k = 0, d = 5 ---
+1 -2 +3 -4 = +5
+0 +1 +14 -11 = +19
+0 +14 -8 +21 = -26
+9 +7 +3 +5 = +4
--- k = 0, d = 9 ---
+1 -2 +3 -4 = +5
+0 +1 +14 -11 = +19
+0 +14 -8 +21 = -26
+0 +25 -24 +41 = -41
--- k = 1, d = 14 ---
+1 -2 +3 -4 = +5
+0 +1 +14 -11 = +19
+0 +0 -204 +175 = -292
+0 +25 -24 +41 = -41
--- k = 1, d = 25 ---
+1 -2 +3 -4 = +5
+0 +1 +14 -11 = +19
+0 +0 -204 +175 = -292
+0 +0 -374 +316 = -516
--- k = 2, d = 1.83333 ---
+1 -2 +3 -4 = +5
+0 +1 +14 -11 = +19
+0 +0 -204 +175 = -292
+0 +0 +0 -4.83333 = +19.3333
x1 = 1.000000
x2 = 3.000000
x3 = -2.000000
x4 = -4.000000
[/code]