電子書籍の厳選無料作品が豊富!

こちらのプログラム、もう少しわかりやすく書けないでしょうか?
というよりNは3だとして、for文を使わずに同じ計算過程を何回か書く、ようはfor文でまとめられる前?のようなプログラムにして頂けないでしょうか?
for文を使わないでプログラムを表したいです。ちなみに、for文を使わない場合変数k,i,jは定数として置かれるのでしょうか?
まぁ、場合分けをまとめたのがfor文だと思うのでfor文を使わないならば変数に定数が入ると思いますが。
どうかよろしくお願いします。

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


以下は全体のプログラムです。
/*********************************************
* 連立方程式の解法 ( ガウスの消去法 )
*********************************************/
#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文を使わない場合、
    k=0のときi=1など、k=0のときi=2など場合分けと地道な計算のプログラムになると思いますが、
    以上のような地道な計算が見たいです。

      補足日時:2018/07/26 09:37
  • // 前進消去
    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が3つありますが、どの順番でforが働いているのかわかりません。
    二重まではわかるのですが、三重はさっぱりわかりません。
    forの働きがわからないとk,i,jの変化がわからなくなります。
    どうかよろしくお願いします。

      補足日時:2018/07/26 12:18

A 回答 (8件)

う~ん、こういうのはどうでしょう。


前進消去の
for (j = k + 1; j <= N; j++)

for (j = 0; j <= N; j++)
に変えてみる。これでちゃんと動くので
前進消去が終わったところで
配列をダンプしてみる。
綺麗な上三角になっているはず。


行列の変化が教科書の通りになるので
前進消去がKひとつ分、つまり前進消去のー行分
でどう変化するか、デバッガやダンプで
追うのも良いでしょう。
    • good
    • 0

マジ?



二重も三重も同じ。内側が先に回る。
    • good
    • 0

No.5です。


失礼、jとiが逆でした。

誤り
k  j  i
0  1  1 ループ1回目

正解
k  i  j
0  1  1 ループ1回目
    • good
    • 0

#define N 4 なので



for (k = 0; k < N -1; k++){} のkは、0,1,2と変化する。

その中で
for (i = k + 1; i < N; i++){} のiは、k+1,k+2,…,N-1(=3)と変化する。

その中で
for (j = k + 1; j <= N; j++){} のjは、k+1,k+2,…、N(=4)と変化する。

従って一番内側のforの{}の中はk,i,jの値が以下の組み合わせで変化します。

k  j  i
0  1  1 ループ1回目
0  1  2 ループ2回目
0  1  3 ループ3回目
0  1  4 ループ4回目
0  2  1 ループ5回目
0  2  2 ループ6回目
0  2  3 ループ7回目
0  2  4 ループ8回目
0  3  1 ループ9回目
0  3  2 ループ10回目
0  3  3 ループ11回目
0  3  4 ループ12回目
1  2  2 ループ13回目
1  2  3 ループ14回目
1  2  4 ループ15回目
1  3  2 ループ16回目
1  3  3 ループ17回目
1  3  4 ループ18回目
2  3  3 ループ19回目
2  3  4 ループ20回目

各ループ時の k,i,jの値を式の中に当てはめてみればよろしいかと思います。
    • good
    • 0

No.3です。

補足文を見ました。

>どの順番でforが働いているのかわかりません。

次のプログラムを実行してみてください。これで順番ぐらいはわかるでしょう。
int i = -1, j = -1, k = -1;
for (i=0; i<3; i++) {
printf("for i: i=%d, j=%d, k=%d\n", i, j, k);
for (j=0; j<3; j++) {
printf("for j: i=%d, j=%d, k=%d\n", i, j, k);
for (k=0; k<3; k++) {
printf("for k: i=%d, j=%d, k=%d\n", i, j, k);
}
}
}

複雑なことを一足飛びにやろうとするから混乱するのだと思います。わからない部分を簡単な例題に置き換えて理解の助けにする、といった姿勢で臨むと、自己解決できるようになると思います。一見すごく面倒くさいことを繰り返すように思うかもしれませんが、次に類似の疑問がわいたときにこういった経験が必ず役に立ちます。
    • good
    • 0

>ようはfor文でまとめられる前?のようなプログラムにして頂けないでしょうか?



こういうのは人にやってもらうのではなくて自分でするものです。人に作ってもらったところで何も理解したことになりません。自分でやるから意味があると思います。

こんな感じにやります。

x = 0;
for (i=0; i<3; i++) {
x += a[i];
printf("i=%d, x=%d\n", i, x);
}

ならば、

x = 0;
i = 0;
x += a[i];
printf("i=%d, a[i]=%d, x=%d\n", i, a[i], x);
i ++;
x += a[i];
printf("i=%d, a[i]=%d, x=%d\n", i, a[i], x);
i ++;
x += a[i];
printf("i=%d, a[i]=%d, x=%d\n", i, a[i], x);
// i++するとi<3に反するのでここで終わり

です。ここでは、forを忠実に再現するためi++としていますが、iにあたる部分に直接数値を書いても構わないと思います。
ご質問文ではforが入れ子になっていますが、やることは大差ありません。
    • good
    • 0

えっと。

。。

プログラム(ソフトウェア)を作る際は最初に設計をしましょう。
大切なのは処理手順を日本語(日常使っている母国語)で書き表すことです。
箇条書きを使ったり、何らかのチャート図をご存知したらそれを使って書き表します。
箇条書きの場合は単に、、、

(1) ...
(2) ...
(3) ...

というものではなく、条件分岐や繰り返し処理が明確に分かるよう、、、

(1) ...
(2) ...
 1) ...
 2) ...
(3) ...

といった構造を持った書き方をすると頭の中にある処理手順を正確に書きだしやすくなります。
コーディングはこれを使用するプログラミング言語に翻訳するだけの作業です。
ですので設計のかなりの部分は使用するプログラミング言語に依存せずに書ける場合が多いです。
ただし、通常の手続き型言語とオブジェクト指向言語ではモジュール(クラス)設計が異なりますので、そこを意識する部分は変わらざるを得ませんが。。。

ちなみに蛇足ですが、ソースコードの全ての行を1文字目から書くと処理構造が大変わかりにくくなります。
if文やfor文などの構造(=処理範囲ですね)がわかるようタブを上手に使うと後から読みやすくデバッグもしやすいです。
コーディングルールを作って統一されるとよいです。

参考まで。
    • good
    • 0

>こちらのプログラム、もう少しわかりやすく書けないでしょうか?


何をもって「わかりやすい」かは意見の分かれるところですが、
>for文を使わずに同じ計算過程を何回か書く
ことは可能でしょう

>プログラムにして頂けないでしょうか?
ご自分のハンドコーディングで展開されればよろしいかと

>for文を使わない場合、
>k=0のときi=1など、k=0のときi=2など場合分けと地道な計算のプログラムになると思いますが、
>以上のような地道な計算が見たいです。
ご自由に。
    • good
    • 3

お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!