• ベストアンサー

行列をべき乗させるプログラム

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

質問者が選んだベストアンサー

  • ベストアンサー
回答No.2

#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回呼び出した方が綺麗だと思う 面倒なので書かないけど,ここまで自力でコード書く人なら これだけできちんと書けるだけの人なはず。頑張ってね! */

naka777008
質問者

お礼

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

その他の回答 (2)

  • aigaion
  • ベストアンサー率47% (287/608)
回答No.3

他の方が指摘をされているので,サンプル書いてみました. ------ 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に向かう前に,紙に式などを書いてみると返って早く完成しますよ.

naka777008
質問者

お礼

なるほどー こっちの方がシンプルですね! わかりやすく書いていただきありがとうございます! 一応先に紙に書いてから作ってるんですが、まだ勉強し始めて 1週間ちょっとなのでまだまだ完成に至るまでには甘いです・・・

  • redfox63
  • ベストアンサー率71% (1325/1856)
回答No.1

デバッガを使って 変数の値を追いかけましょう 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]の値はどうなっているのが正常なのでしょう

naka777008
質問者

お礼

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