アプリ版:「スタンプのみでお礼する」機能のリリースについて

2行2列を5乗させるプログラムを作って、一応できたつもりだったんですが結果が合いません・・・
何かヒントでもいいのでわかる方いらっしゃいましたらよろしくお願いします。

<プログラム>
#include <stdio.h>

#define N 2

int A[N][N];
int A_NEW[N][N];
int A_5[N][N]; /* 行列Aを5乗したもの */

int main()
{
int i,j,k,l;

/* 2行2列の係数行列Aの成分を入力 */
printf("係数行列Aを%d行%d列で入力してください\n", N, N);

for( i=0; i<N; i++)
{
for( j=0; j<N; j++)
{
printf("A[%d][%d]=", i+1, j+1);
scanf("%d", &A[i][j]);
}
}

for(i=0; i<N; i++)/* A_NEW=A*Aの計算 */
{
for(j=0; j<N; j++)
{
for(k=0; k<N; k++)
{
A_NEW[i][j] += A[i][k] * A[k][j];
}
}
}

for(l=0; l<3; l++)
{
for(i=0; i<N; i++)/* A_5の計算 */
{
for(j=0; j<N; j++)
{
for(k=0; k<N; k++)
{
A_5[i][j] += A_NEW[i][k] * A[k][j];
}
}
}

for(i=0; i<N; i++)
{
for(j=0; j<N; j++)
{
A_NEW[i][j] = A_5[i][j];
}
}
}

printf("A_5=\n"); /* 出力 */

for( i=0; i<N; i++)
{
for( j=0; j<N; j++)
{
printf("%d ", A_5[i][j]);
}
printf("\n");
}
}


<入力例>
A=
1 3
2 1

<期待する結果>
A=
241 303
202 241

<このプログラムの結果>
406 498
332 406

A 回答 (3件)

デバッガを使って 変数の値を追いかけましょう



for(i=0; i<N; i++) /* A_NEW=A*Aの計算 */
{
  for(j=0; j<N; j++)
  {
    for(k=0; k<N; k++)
    {
      A_NEW[i][j] += A[i][k] * A[k][j];
    }
  }
}
のループの中で A_NEW[i][j]の期待する値と実際の値を比べて見ましょう
+= で代入 & 加算をしているので kのループに入る前のA_NEW[i][j]の値はどうなっているのが正常なのでしょう
    • good
    • 0
この回答へのお礼

ご意見ありがとうございます。
ただ、まだデバッガの使い方を習っていないのでわからないです・・・
代わりにprintfで逐次調べてみます!

お礼日時:2008/07/22 10:03

#include <stdio.h>



#define N 2

int A[N][N];
int A_NEW[N][N];
int A_5[N][N]; /* 行列Aを5乗したもの */

int main()
{
int i,j,k,l;

/* 2行2列の係数行列Aの成分を入力 */
printf("係数行列Aを%d行%d列で入力してください\n", N, N);

for( i=0; i<N; i++)
{
for( j=0; j<N; j++)
{
printf("A[%d][%d]=", i+1, j+1);
scanf("%d", &A[i][j]);
}
}

for(i=0; i<N; i++) /* A_NEW=A*Aの計算 */
{
for(j=0; j<N; j++)
{
for(k=0; k<N; k++)
{
A_NEW[i][j] += A[i][k] * A[k][j];
}
}
}

for(l=0; l<3; l++)
{
for(i=0; i<N; i++) /* A_5の計算 */
{
for(j=0; j<N; j++)
{
for(k=0; k<N; k++)
{
A_5[i][j] += A_NEW[i][k] * A[k][j]; /* …P */
}
}
}

for(i=0; i<N; i++)
{
for(j=0; j<N; j++)
{
A_NEW[i][j] = A_5[i][j];
}
}

/* 一端0に戻さないと残存している結果にPを足されることになる …Q*/

for(i=0; i<N; i++)
{
for(j=0; j<N; j++)
{
A_5[i][j] = 0;
}
}


}

printf("A_5=\n"); /* 出力 */

for( i=0; i<N; i++)
{
for( j=0; j<N; j++)
{
printf("%d ", A_NEW[i][j]); /* Qで0に戻しちゃったので出力結果の変数が変わっています。*/
}
printf("\n");
}
}

/*
ただ,個人的には,二つの行列を計算するだけの関数を分けて
mainから5回呼び出した方が綺麗だと思う
面倒なので書かないけど,ここまで自力でコード書く人なら
これだけできちんと書けるだけの人なはず。頑張ってね!
*/
    • good
    • 0
この回答へのお礼

なるほど!
完全に理解できました。
加筆修正ありがとうございます!
次は関数使って書いてみます!

お礼日時:2008/07/22 10:06

他の方が指摘をされているので,サンプル書いてみました.


------
int A[N][N] = {{1,3},{2,1}};//入力
int R[N][N] = {{1,0},{0,1}};//出力 単位行列で初期化
int i, j, k,l;

for(l = 0; l < 5; l++){
  //i行目の処理
  for (i = 0; i < N; i++) {
    //i行目をTに記憶
    int T[N];
    for (k = 0; k < N; k++)
      T[k] = R[i][k];
    //i行目の計算
    for (j = 0; j < N; j++) {
      //i行j列目を計算
      int tmp = 0;
      for (k = 0; k < N; k++)
        tmp += T[k] * A[k][j];
      R[i][j] = tmp;
    }
  }
}
------
R = R * A
積の計算では,Rのi行目の計算を始める前にまず,i行目を記憶.
記憶したi行目とAのi列目を計算してRのi行目へ記憶としています.
こうすることで,RとAだけで計算を進めることができます.

5乗の計算は,入力としてR,A(入力)を取り,出力としてRを出力するようにしてみました.
Rの初期値を R = E(Eは単位行列) として R = R * A を5回まわしています.
一回目は,R = E * A = A,2回目は R = R * A = Aの2乗となっていきます.

定式化(設計)をきっちりとせずにコーディングに移ると,その場で作った曖昧な処理がうまく働かないことが多いので
PCに向かう前に,紙に式などを書いてみると返って早く完成しますよ.
    • good
    • 0
この回答へのお礼

なるほどー
こっちの方がシンプルですね!
わかりやすく書いていただきありがとうございます!

一応先に紙に書いてから作ってるんですが、まだ勉強し始めて
1週間ちょっとなのでまだまだ完成に至るまでには甘いです・・・

お礼日時:2008/07/22 10:12

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