• 締切済み

行列に関して。

以下の行列を対角成分が最も大きくなるような プログラムをつくりたいのですが 0   1   4  3 7   0   1  -5 1    3   0   7 -2   4   4  -8 #include<stdio.h> #include<math.h> #include<stdlib.h> #define NUM 4 int main(){ /* 初期化 */ int i; /* ループ変数 (行)*/ int j; /* ループ変数 (列)*/ int k; /* ループ変数 */ int imax; /* 最大値のi成分 */ int jmax; /* 最大値のj成分 */ double nmax; /* 最大値を入れるための変数 */ double tmp; /* ソートのための一時的な変数 */ double eps = 1.0e-6; /* 判定値 */ double a[NUM][NUM] = { { 0.0, 1.0, 4.0, 3.0}, { 7.0, 0.0, 1.0, -5.0}, { 1.0, 3.0, 0.0, 7.0}, {-2.0, 4.0, 4.0, -8.0}}; /* 対象とする要素位置 = k */ for( k = 0 ; k < NUM ; k++ ){ /*対象とする要素位置 = k*/ nmax = 0.0;/* 初期化 */ imax = k;/* 初期化 0とは限らない */ jmax = k;/* 初期化 0とは限らない */ /* 1.絶対値の最大値を求める */ for( i = k ; i < NUM ; i++ ){ for( j = k ; j < NUM ; j++ ){ if(fabs(nmax) < fabs(a[i][j])){ nmax = a[i][j]; imax = i; jmax = j; /* 対象としている行列要素の中で,最大となる行列要素のi,j成分を探す */ /*ここに絶対値の最大値を求め、nmax、imax、jmaxに代入するプログラムを書く*/ /*絶対値の求め方、数学関数fabs(x)を用いる*/ } } } /* 2.行入れ換え */ if( k != imax ){/* 対象としている行と最大値を持つ行が同じなら,入れ替える必要が無い */ for( j = 0 ; j < NUM ; j++ ){ tmp=a[k][j]; a[k][j]=a[imax][j]; a[imax][j]=tmp;/* 対象としている行と最大値を持つ行との入れ替え */ /*ここに行の入れ替え行うプログラムを書く*/ } } /* 3.列入れ換え */ if( k != jmax ){/* 対象としている列と最大値を持つ列が同じなら,入れ替える必要が無い */ for( i = 0 ; i < NUM ; i++ ){ tmp=a[i][k]; a[i][k]=a[i][imax]; a[i][imax]=tmp;/*対象としている列と最大値を持つ列との入れ替え*/ /*ここに列の入れ替え行うプログラムを書く*/ } } } /* 結果の出力 */ for(i=0; i<NUM; i++){ for(j=0; j<NUM; j++){ printf("%5.1f ",a[i][j]); } printf("\n"); } /*ここに行列の表示プログラムを書く*/ return(0); } 上のぷろぐらむを実行しても、1個目のfor文の1ループ目で終了してしまい 1行目と、4行目を交換、4列目と1列目を交換した行列だけが表示されます。 結果が以下のような行列にするにはどう改善すればよいでしょうか? -8.0   -2.0  4.0  4.0 -5.0   7.0  1.0  0.0   3.0   0.0  4.0  1.0  7.0   1.0  0.0  3.0 です。

みんなの回答

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

後者であるなら当方の環境では WinXPSP3 + VC6 お示しのコードで列入れ替えのimaxをjmaxに修正すれば 期待通りの動きになりましたよ 行入れ替えが行われているのか確認 /* 2.行入れ換え */ if( k != imax ){/* 対象としている行と最大値を持つ行が同じなら,入れ替える必要が無い */ printf( "行入れ替え %d\n", k ); // 追加 for( j = 0 ; j < NUM ; j++ ){ 列入れ替えが行われているのか確認 /* 3.列入れ換え */ if( k != jmax ){/* 対象としている列と最大値を持つ列が同じなら,入れ替える必要が無い */ printf( "列入れ替え %d\n", k ); // 追加 for( i = 0 ; i < NUM ; i++ ){ ループの終端で変数kが破壊されていないかを確認 } } printf( "ループ %d\n", k ); // 追加 } /* 結果の出力 */ for(i=0; i<NUM; i++){ for(j=0; j<NUM; j++){ といった具合でどこがバグっているのかを確認しましょう

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

0   1   4  3 7   0   1  -5 1    3   0   7 -2   4   4  -8 で初回の検索で『-8』が候補に挙がり 0と3行を入れ替え 列の入れ替えはどのようにするのでしょう 入れ替えられた行のa[0][0]とa[0][3]を入れ替えるだけなのか それとも列全体{a[0][0],a[1][0],a[2][0],a[3][0]}と{a[0][3],a[1][3],a[2][3],a[3][3]}を入れ替えるのか ・・・

nanokea
質問者

お礼

こんばんわ。 列の入れ替えは、後者の通り入れ替えるようになっています。

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

列の入れ替えはk行内だけの話ですか? -8.0 4.0 4.0 -2.0 0.0 7.0 1.0 -5.0 1.0 3.0 7.0 0.0 0.0 1.0 3.0 4.0 がこんな感じではないのでしょうか ・・・ 初回のループは16項目中の最大値 2回目は 2行目以降の12個中の最大値 3回目は 3行目以降の8個中の最大値 4回目は 4行目内の最大値 を探すのでしょうか お示しのコードだと 最初は16項目、2回目が a[1][1]からa[3][3]の9個 3回目がa[2][2]からa[3][3]の4個 4回目はa[3][3]のみしか見ていません ・・・ 結果出力の 1つ手前の } 前に 中間結果を k,imax,jmax と共に出力して期待する結果と合致していない部分を探してみましょう

nanokea
質問者

お礼

返信ありがとうございます! >お示しのコードだと 最初は16項目、2回目が a[1][1]からa[3][3]の9個 3回目がa[2][2]からa[3][3]の4個 4回目はa[3][3]のみしか見ていません ・・・ そうなんです。そのように最大値を探すようにつくるようにとかかれておりました。 詳細のせてなくてすみません。

  • garaogu
  • ベストアンサー率40% (67/166)
回答No.1

こんばんは 列入れ替えのループ内で、配列変数の配列要素を指し示す変数が、jmaxであるべき所を、imaxと間違えているからではないでしょうか? 以下のようにすれば良いのではないでしょうか? /* 3.列入れ換え */ if( k != jmax ){/* 対象としている列と最大値を持つ列が同じなら, 入れ替える必要が無い */ for( i = 0 ; i < NUM ; i++ ){ tmp=a[i][k]; a[i][k]=a[i][jmax]; a[i][jmax]=tmp;/*対象としている列と最大値を持つ列との入れ替え*/ /*ここに列の入れ替え行うプログラムを書く*/ } }

nanokea
質問者

お礼

迅速な回答ありがとうございます! うっかりミスしていました。 確かにそのように変更したところ、確かな表示がでました。 ありがとうございました!

関連するQ&A

  • 行列の行の入換え

    | -1 -1 -2 -1 10 | | -1 -2 -1 10 -1 | | -2 -1 10 -1 -1 | | -1 10 -1 -1 -2 | | 10 -1 -1 -2 -1 | この行列を次の順序で並び替えたいのですが 1.第1列にある要素の中で絶対値の最大値がある行を探し,その行と第1行を入れ換える. 2.第2列にある要素の中で絶対値の最大値がある行を第2行以下から探し,その行と第2行を入れ換える. 3.これを左上から右下へ順次移動して,行の入れ換えを行う. #include<stdio.h> #include<math.h> #define N 5 #define M 5 int main(){ float a[N][M]={{-1.0,-1.0,-2.0,-1.0,10.0},{-1.0,-2.0,-1.0,10.0,-1.0},{-2.0,-1.0,10.0,-1.0,-1.0}, {-1.0,10.0,-1.0,-1.0,-2.0},{10.0,-1.0,-1.0,-2.0,-1.0}}; float nmax; int i,j,k=0,s,imax; for(j=0; j<M; j++){ nmax = a[0][j]; imax = 0; for(i=1; i<N; i++){ if(fabs(nmax) < fabs(a[i][j])){ nmax = a[i][j]; imax = i; } } for(j=0; j<M; j++){ s=a[k][j]; a[k][j]=a[imax][j]; a[imax][j]=s; } k++; } for(i=0; i<N; i++){ for(j=0; j<M; j++){ printf("%5.1f ",a[i][j]); } printf("\n"); } return(0); } このように作成したのですが、1行目と5行目しかいれかわりません。 なぜでしょうか??

  • 初心者な質問その5

    ************************************************************************* void mmul(double a[],double b[],double c[],int imax,int jmax,int kmax){ int i,j,k; for(i=0;i<imax;i++){ for(k=0;k<kmax;k++){ c[(1)]=0.0; for(j=0;j<jmax;j++){ c[i*kmax+k] += a[(2)]*b[(3)] } } } } ************************************************************************* 行列の乗算を計算するプログラムです。 ⅰ,(1)~(3)に入る式 ⅱ,この関数mmulを使って下の行列を計算するプログラム についてお願いします。

  • 行列の計算について。

    こんにちは。 JAVAで行列の計算をするプログラムを作っていますが、なかなかうまくいきません。 自分で考えたのはfor文を使った物です。行列数を入力するとその数だけの行列を作る、という物なのですが、どうもうまくいきません。 「2」を入力すると、 │1 2││5 6│ │   ││   │ │3 4││7 8│ こんな2行2列の行列の計算をする、というものです。 for (int i =0; i < 2; i++){ for (int j = 0; j<2; j++){ for (int k = 0; k<2; k++){ C[i][j]=C[i][j]+a[i][k]*b[k][j]; } } } 上のようなプログラムを考えました。 JAVAには行列の計算をする専用の関数(クラス?)などあるのでしょうか? また、ソースなど教えていただけると、とても助かります。 CからJAVAに急に移ったので、つまづくことが非常に多いです。 よろしくお願いします。

    • ベストアンサー
    • Java
  • 逆行列のアルゴリズム

    現在逆行列を求めるアルゴリズムを勉強してるんですが、全然わかりません。 とあるサイトさんから逆行列を求めるソースを拝借させていただきました。 実際に2行2列の値を入れて手計算でプログラムを追っていったら23行目で対角成分に1を代入したり、33行目で対角成分以外の成分に0を代入しているのはわかるんですが、わかるのはその程度で、もっと詳しくアルゴリズムを教えていただきたいです。 わかりやすいサイトなどでも結構なんで教えていただけると助かります! よろしくおねがいします。 #include <stdio.h> 01:int main(void) 02:{ 03: 04: double exp_At[2][2]={{1,3},{2,1}}; //入力用の配列 05: double inv_exp_At[2][2]; //ここに逆行列が入る 06: double buf; //一時的なデータを蓄える 07: int i,j,k; //カウンタ 08: int num=2; //配列の次数 09: //単位行列を作る 10: for(i=0;i<num;i++) 11: { 12: for(j=0;j<num;j++) 13: { 14: inv_exp_At[i][j]=(i==j)?1.0:0.0; 15: } 16: } 17: /* 掃き出し法 */ 18: for(i=0; i<num; i++) /* 逆行列をexp(-At)求める */ 19: { 20: buf=1/exp_At[i][i]; 21: for(j=0; j<num; j++) 22: { 23: exp_At[i][j] *= buf; 24: inv_exp_At[i][j] *= buf; 25: } 26: for(j=0; j<num; j++) 27: { 28: if(i != j) 29: { 30: buf=exp_At[j][i]; 31: for(k=0; k<num; k++) 32: { 33: exp_At[j][k] -= exp_At[i][k] * buf; 34: inv_exp_At[j][k] -= inv_exp_At[i][k] * buf; 35: } 36: } 37: } 38: } 39://逆行列を出力 40: 41: printf("逆行列exp(-At)=\n"); 42: 43: for(i=0;i<num;i++) 44: { 45: for(j=0;j<num;j++) 46: { 47: printf(" %f",inv_exp_At[i][j]); 48: } 49: printf("\n"); 50: } 51:}

  • c言語 行列の積に関して

    <問>  4行3列の行列aと3行4列の行列bの積を、4行4列の行列cに格納する関数を作成せよ。  void mat_mul(const int a[4][3], const int b[3][4], int c[4][4]) 入門レベルのスキルしかありません。 上手く行列の積のプログラムが組めません。 行列の積の計算結果が何も出てきません。 どの様にしたら良いかご指導の程、宜しくお願いします。 <プログラム>  void mat_mul(const int a[4][3], const int b[3][4], int c[4][4]) { int i, j, k; for (i = 0; i < 4; k++) { for (j = 0; j < 4; i++) for (k = 0; k < 3; j++) c[i][j] = c[i][j] + (a[i][k] * b[k][j]); } } void mat_print(const int m[4][4]) { for (int i = 0; i < 4; i++) { for (int j = 0; j < 4; j++) printf("%4d", m[i][j]); putchar('\n'); } } int main(void) { int i, j ,k; int tensu1[4][3]; int tensu2[3][4]; int seki[4][4]; for(i = 0; i < 4; i++) { for (j = 0; j < 3; j++) { scanf("%d", &tensu1[i][j]); } putchar('\n'); } for(i = 0; i < 3; i++) { for(j = 0; j < 4; j++){ scanf("%d", &tensu2[i][j]); } putchar('\n'); } putchar('\n'); mat_mul(tensu1, tensu2, seki); puts("行列の積"); mat_print(seki); return 0; }  

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

    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

  • 行列の積を関数を使って求める・・?

    2つの行列の行と列を入力し、積を計算するプログラムを関数を使って書きたいのですが、上手く行きません。どこをどのように直したらよいか教えてください!お願いします!! 以下が私が書いたプログラムです。 #include<stdio.h> #define NUMBER 10 int first(int x1,int x2,int y1,int y2,int i,int j,int k) { int a[NUMBER][NUMBER] = {0}; int b[NUMBER][NUMBER] = {0}; int c[NUMBER][NUMBER] = {0}; do{ printf("2つの行列の行と列を入力してください\n"); scanf("%d", &x1); scanf("%d", &x2); scanf("%d", &y1); scanf("%d", &y2); if(x1 != y2){ printf("行列の積は計算できません\n"); } }while(x1 != y2); printf("行列Aの要素を入力してください\n"); for(i=0; i<x1; i++){ for(j=0; j<x2; j++) scanf("%d", &a[i][j]); } printf("行列Bの要素を入力してください\n"); for(j=0; j<y1; j++){ for(k=0; k<y2; k++) scanf("%d", &b[j][k]); } } int second(int x1,int x2,int y1,int y2,int i,int j,int k) { int a[NUMBER][NUMBER] = {0}; int b[NUMBER][NUMBER] = {0}; int c[NUMBER][NUMBER] = {0}; for(i=0; i<x1; i++){ for(k=0; k<y2; k++){ for(j=0; j<x2; j++) c[i][k] = c[i][k] + a[i][j]*b[j][k]; } } for(i=0; i<x2; i++){ for(k=0; k<y2; k++) printf("%3d", c[i][k]); printf("\n"); } } int main(void) { int a[NUMBER][NUMBER] = {0}; int b[NUMBER][NUMBER] = {0}; int c[NUMBER][NUMBER] = {0}; printf("行列の積を計算します\n %d\n", first(x1,x2,y1,y2,i,j,k)); printf("行列Aと行Bの積は\n %3d",second(x1,x2,y1,y2,i,j,k)); }

  • C言語 多重配列に関して

    以下のプログラムについての質問です。 10行目 for i = 0 の時、13行目 for j = 0 で scanf("%lf", &a[0][0])に10と代入します。 この時のドス画面は input 1-th line element:10 です。ここまではいいのですが、この次がよくわかりません。私の考えでは、10行目 i = 0 の時 13行目 j = 1 となって j がNMAXまでやったら、10行目のiが1になってまた同じように動いて、10行目の i がNMAXになったら、for文が終わると考えたのですが、このプログラムの実行結果(一番下にあります)を見てみると自分の考えが間違っていることに気がつきました。 3行3列のプログラムなので、a[0][0] a[0][1] a[0][2] a[1][0].......となると考え、scanfでドス画面に9回数字を打ち込むかと思ったのですが実際は3回でした。このプログラムはどのように読んだら良いのでしょうか?? 回答宜しくお願い致します。 1  #include <stdio.h> 2  #define NMAX 3 3 4  main() 5  { 6   double a[NMAX] [NMAX], b[NMAX] [NMAX], c[NMAX] [NMAX]; 7   int i,j,k; 8 9   printf("matrix 1:\n"); 10   for(i=0; i< NMAX; i++) 11   { 12   printf("input %d-th line element:", i+1); 13   for(j=0; j< NMAX; j++); 14   { 15   scanf("%lf", &a[i][j]); 16   } 17   } 18   printf("matrix 2:\n"); 19   for(i=0; i<NMAX; i++) 20   { 21   printf("input %d-th line element:", i+1); 22   for(j=0; j< NMAX; j++); 23   { 24   scanf("%lf", &b[i] [j]); 25   } 26   } 27  for(i=0; i<NMAX; i++) 28   { 29   for(j=0; j<NMAX; j++) 30   { 31   c[i][j] = 0; 32   for(k=0; k <NMAX; k++) 33   { 34   c[i][j] += a[i][k] * b[k][j]; 35   } 36   } 37   } 38 39  printf("matrix 1 * matrix2 = :\n"); 40  for(i=0; i<NMAX; i++) 41   { 42   printf("["); 43   for(j=0;j<NMAX; j++) 44   { 45   printf("%f", c[i][j]); 46   } 47   printf("]\n"); 48   } 49  }

  • 塗る部分と塗らない部分を条件によってわけたいのですが・・・

    今回困っているのは下のマクロで (1)紺なら足跡を残し、青なら進んでいるセルだけ青にして前回の青の足跡は残さないで (2)セルが紺の足跡でいっぱいになるまで、これを続けます。 この条件をここに追加しようと思ったのですが、なかなかうまく行きません。ヒントだけでも、何か名案がありましたらご回答お願いします。 Const IMAX As Long = 30 '最大 i 座標 Const JMAX As Long = 20 '最大 j 座標 Const NMAX As Long = 50 '最大ステップ数 Const motigomi As Long = 5 'ゴミ「○歩につき●個捨てる」数 Dim ip(MMAX) As Long '人の i 座標 Dim jp(MMAX) As Long '人の j 座標 Dim occ(IMAX, JMAX) As Long Dim pre(IMAX, JMAX) As Integer Dim post(IMAX, JMAX) As Integer Sub ashiato() Randomize Cells.Clear For n = 1 To NMAX 'ステップを進める For m = 1 To 1   iprev = ip(m) '元いた位置 jprev = jp(m) '移動先 (i, j) を決める i = i - 1 '周期境界条件 If i > IMAX Then i = i - IMAX If i < 1 Then i = i + IMAX If j > JMAX Then j = j - JMAX If j < 1 Then j = j + JMAX '実際に移動 ip(m) = i jp(m) = j '色付けを更新 pre(i, j) = Int(motigomi * Rnd()) If pre(i, j) = 1 Then Cells(i, j).Interior.color = RGB(10, 50, 100) Else Cells(iprev, jprev).Clear Cells(i, j).Interior.color = RGB(40, 50, 400) End If Next Next End Sub

  • 行列式のプログラムでのループがわかりません。

    行列式を求めるプログラムを考えていて、一応はちゃんと答えがでるのですが、 ループを使って計算させようとしたのですがイマイチわかりません。 #include <stdio.h> main() {     int a[3][3]={{1,2,2},{-1,5,3},{2,0,1}};     int i,j,n;     for(i=0;i<3;i++)     {          for(j=0;j<3;j++)              printf("%3d",a[i][j]);              printf("\n");     }     n=a[0][0]*(a[1][1]*a[2][2]-a[1][2]*a[2][1])      -a[1][0]*(a[0][1]*a[2][2]-a[0][2]*a[2][1])      +a[2][0]*(a[0][1]*a[1][2]-a[0][2]*a[1][1]);     printf("この行列の行列式は \n");     printf("%d \n",n); } 1 2 2 -1 5 3 2 0 1 という行列式です。 nの処理をループを使うとどう書いたらいいでしょうか? これはたまたま3行3列だからひとつひとつ指定して計算できますが これが4行4列とかだったら絶対ループ使わなきゃ面倒ですからね~。 とりあえず3行3列のが理解できたらいいとは思うのですがなかなか複雑で難しいですね。

専門家に質問してみよう