• ベストアンサー

行列の積のプログラム

n次正方行列X=(xij),Y=(yij)の積XYの(i,j)成分はΣ(k=1,n)xikykjで定義する。これをmin{k∈1,2,…n}(xik+ykj)と変更したとき行列の積を計算するプログラムの作成をしたいです。 ※minXは、Xの中の最小値を意味する。 十進BASICで解きたいのですが、以下のプログラムで間違いがあったら指摘してただけないでしょうか?よろしくお願いします。 INPUT N DIM X(n,n) DIM Y(n,n) DIM Z(n,n) INPUT X(n,n) INPUT Y(n,n) FOR i = 1 TO n  FOR j = 1 TO n   LET Z(i,j) = X(i,1) * Y(1,j)    FOR k = 2 TO n     IF Z(i,j) > X(i,k) * Y(k,j) THEN LET Z(i,j) = X(i,k) * Y(k,j)   NEXT k  NEXT j NEXT i INPUT Z(n,n) END

  • tbg
  • お礼率35% (64/178)

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

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

これ前やったなあ。 僕の場合はScheme(Lispの一方言)で書いたんですけど、恐らくBASICで書く以上、「殺人的な長さ」になると思います。 まあ、僕はBASICは良く知らんので、入出力関係ですと、ANo.1さんの方を参照して欲しいんですが、一応ロジックで気づいた事を挙げていきます。 9行目: LET Z(i,j) = X(i,1) * Y(1,j) そもそもここが違います。 題意では、 min{k∈1,2,…n}(xik+ykj) でないとならないので、そもそも掛け算を用いません。 また、配列Zのi行j番目にいきなり計算結果を代入するのも間違っています。 題意的には、例えば4行4列の計算結果、Z_{1,1}に当たる数値の候補は Z_{1,1}=min{x_{1,1}+y_{1,1},x_{1,2}+y_{2,1},x_{3,1}+y_{1,3},x_{1,4}+y_{4,1}} の4つあって、この4つの中から「最小の値」をZ_{1,1}として返さないといけません。つまり、この作業をn行n列の行列Zに対して「全て」やらないとならないのです。 もうちょっと具体的に見てみましょうか? 例えば4行4列の行列Xが、十進BASICの記法を真似ると、 MAT X = 1,0,2,0,0,1,0,2,2,0,1,0,0,2,0,1 で、同様に4行4列の行列Yが、 MAT Y = 16,3,2,3,5,10,11,8,9,6,7,12,4,15,14,1 だった場合、出力結果の行列Zは MAT Z = 4,4,3,1,6,3,2,3,4,5,4,1,5,3,2,2 でないとなりません。 何故なら先ほどの定義により、例えばZ_{1,1}は Z_{1,1}=min{1+16, 0+5 , 2+9 , 0+4} となり(MAT Yの要素を4つづつに分けて、その先頭要素が計算に使われていることに注意!)「その中の最小値」の4がZ_{1,1}の計算結果として出力されます。 どのXの要素とどのYの要素が計算に使われるのか、は普通の「行列の積」に従ってるんですけど、この問題の場合、根本的にn行n列同士の計算を行うと、各要素に対してなおかつ「n個の要素から」最小値を返す、ってのが題意です。 従って、例示したプログラムにはその計算過程が組み込まれていないように見受けられます。 根本的なロジックを見直した方が良いでしょうね。

tbg
質問者

お礼

詳しい解説ありがとうございます。 とても勉強になりました!

その他の回答 (2)

  • fronteye
  • ベストアンサー率43% (118/271)
回答No.3

No.1です。 No.2さんの回答でmin{k∈1,2,…n}(xik+ykj)の意味がわかりました。 それならば簡単なことです。 FOR~NEXT内の乗算(*)を加算(+)に変えるだけです。 No.2さんの提示した例を入力しましたが、正しい結果が出力されましたよ。

tbg
質問者

お礼

回答ありがとうございます、補足までしていただき本当に感謝です。 もっとプログラミングの勉強頑張りたいと思います。

  • fronteye
  • ベストアンサー率43% (118/271)
回答No.1

minXの定義がいまいちわからないので、プログラムの内容ではなく文法へのアドバイスをします。 十進BASICでは、配列へ数値を入力するのはMAT INPUT文を使います。 n=2ならば、5,4,9,3のように配列の要素分の数値をカンマで区切って入力します。 最後のINPUT Z(n,n)は出力だと思います。 MAT PRINT文を使います。 INPUT N DIM X(n,n) DIM Y(n,n) DIM Z(n,n) MAT INPUT X MAT INPUT Y FOR i = 1 TO n FOR j = 1 TO n LET Z(i,j) = X(i,1) * Y(1,j) FOR k = 2 TO n IF Z(i,j) > X(i,k) * Y(k,j) THEN LET Z(i,j) = X(i,k) * Y(k,j) NEXT k NEXT j NEXT i MAT PRINT Z END

関連するQ&A

  • 行列の積のプログラム

    n次正方行列X=(xij),Y=(yij)の積XYの(i,j)成分はΣ(k=1,n)xikykjで定義される。これをmin{k∈1,2,…n}(xik+ykj)と変更する。 ※minXは、Xの中の最小値を意味する。 このとき、次の行列D D= 0 6 2 9999 4 0 3 4 9999 1 0 8 9999 2 9999 0 の新しい行列の積の定義によるD^3とD^4を計算せよ。 行列がうまく表せず見にくいと思いますが、4次正方行列となっています。 D^2= 0 3 2 10 4 0 3 4 5 1 0 5 6 2 5 0 D^3= 0 3 2 7 4 0 3 4 5 1 0 5 6 2 5 0 D^4= 0 3 2 7 4 0 3 4 5 1 0 5 6 2 5 0 であっていますか?教えてほしいです。よろしくお願いします。

  • c言語のプログラムで行列の積を計算する

    指定された行・列数(それぞれ10以下とする)の行列 X, Y の積 Z = X × Y を求めるプログラムを作成せよ.行列の要素はすべて整数とする. このプログラムで行と列の成分を入力するときに、1列になってしまうのですがどうしたらちゃんと入力できますか? int main(void) { double A[10][10]; double B[10][10]; int i,j,m,n,p,k; printf("行列xの行数は?:"); scanf("%d",&m); printf("行列xの列数(行列yの行数)は?:"); scanf("%d",&n); printf("行列yの列数は?:"); scanf("%d",&p); printf("行列xを入力してください。\n"); for (i = 0; i < m; i++) { for (j = 0; j < n; j++) { scanf("%d", &A[i][j]); } } printf("行列yを入力してください。\n"); for (i = 0; i < n; i++) { for (j = 0; j < p; j++) { scanf("%d", &B[i][j]); } }

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

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

  • 行列に関するプログラムについて

     『m×n 型行列Aの最大成分と最小成分を捜し、それぞれの行番号と列番号を出力するプログラムを作れ』という問題です。  以下のようにBACICで考えたのですが、うまく行番号と列番号を出力するプログラムを作れません。アドバイスいただければと思います。宜しくお願い致します。 100 INPUT m 110 INPUT n 120 DIM A(m,n) 130 MAT INPUT A 140 FOR i=1 TO m 150 FOR j=1 TO n-1 160 LET s=A(i,j) 170 LET t=A(i,j) 180 IF A(i,j)<A(i,j+1) THEN LET s=A(i,j+1) 190 IF A(i,j)>A(i,j+1) THEN LET t=A(i,j+1) 200 NEXT j 210 NEXT i 220 PRINT "最大成分は";s,"最小成分は";t

  • 行列の積について

    3行3列の行列AとB、およびその和と積を表示するものです #include <stdio.h> int main (void) { int i,j,k; double a[3][3] = {{2.4, 5.5, -8.5},{0.8, 3.7, 1.1},{3.5, -9.1, 2.6}}; double b[3][3] = {{-5.1, 9.8, 2.3},{-4.1, 0.2, -0.3},{3.3, 6.1, -1.3}}; double c[3][3] = {0}; printf(" 行列A\n"); for (i = 0; i < 3; i++){ for (j = 0; j < 3; j++) printf("%5.1f", a[i][j]); printf("\n"); } printf("\n 行列B\n"); for (i = 0; i < 3; i++){ for (j = 0; j < 3; j++) printf("%5.1f", b[i][j]); printf("\n"); } printf("\n 行列A+B\n"); for (i = 0; i < 3; i++){ for (j = 0; j < 3; j++) c[i][j] = a[i][j] + b[i][j]; } for (i = 0; i < 3; i++) { for (j = 0; j < 3; j++) printf("%5.1f", c[i][j]); printf("\n"); } for (i=0; i<3 ; i++){ for (j=0; j<3; j++) for (k=0; k<3; k++) c[i][j] =c[i][j]+ a[i][k]* b[k][j]; } printf("\n 行列AB\n"); for (i = 0; i < 3; i++) { for (j = 0; j < 3; j++) printf("%7.2f", c[i][j]); printf("\n"); } return 0; } これだと積だけが異なった値が出てしまいます。 試しに、積の部分だけで組んでみると正しい答えが出ました。 for文のブロックの組み方がまずいのかなと思っていますが、これ以外だと、行列のレイアウトが崩れてしまいます どのように直したらいいのか、ご教示お願いします

  • C言語、行列の積を求めるプログラムについて

    「次に示す行列x,yの積を求めるプログラムを作成せよ。   x[2][3]={{1,2,3},{4,5,6}} y=[3][2]={{1,5},{5,3},{81}}」 という問題です。自分ではとりあえず、 #include<stdio.h> int main(void) { int i,j; int x[2][3]={{1,2,3},{4,5,6}}; int y[3][2]={{1,5},{5,3},{8,1}}; int xy[3][3]={0}; for(i=0;i<3;i++) for(j=0;j<3;j++) xy[i][j]=x[i][j]*y[i][j]; for(i=0;i<3;i++){ for(j=0;j<3;j++) printf("%3d",xy[i][j]); putchar('\n'); } return 0; } というプログラムを作ってみましたが、ダメでした。 ちゃんと積の表示が出るようにするにはどこをどう変えるべきでしょうか?

  • C言語 行列の積

    行列の積をfor文を使って計算したいです。 #include<stdio.h> int main(void){ int x[2][2]={{1,3},{2,4}}; int y[1][2]={3,2}; int xy[1][2]; int i, j, k; for (i = 0; i < 1; i++) { for (j = 0; j < 2; j++) { xy[i][j] = 0; for (k = 0; k < 2; k++) { xy[i][j] += x[i][k] * y[k][j]; } } } xの二行目の計算からできません。 プログラムの修正をお願いします。

  • c言語で行列の積の値を求める

    行列の成分を入力した後に、 入力された行列は X = 1 2 3 4 5 6 7 8 9 10 11 12 Y = 1 5 2 6 3 7 4 8 のように表示して、(上の数字は適当です。) 行列 X と行列 Y の積を求めて結果を表示するプログラムが作りたいのですが、上手く表示できなくて困っています。 #include <stdio.h> int main(void) { double A[10][10]; double B[10][10]; double C[10][10]; int i,j,m,n,p,k; printf("行列xの行数は?:"); scanf("%d",&m); printf("行列xの列数(行列yの行数)は?:"); scanf("%d",&n); printf("行列yの列数は?:"); scanf("%d",&p); printf("行列xを入力してください。\n"); for (i = 0; i < m; i++) { for (j = 0; j < n; j++) { scanf("%d", &A[i][j]); } } printf("行列yを入力してください。\n"); for (i = 0; i < n; i++) { for (j = 0; j < p; j++) { scanf("%d", &B[i][j]); } } この後にどうすればいいのか教えてください。 よろしくお願いします。

  • 行列の積の求めかた

    行列の積を求めるプログラムを組んだのですがうまく表示されないです。 x=1,2,3  4,5,6 y=1,5  5,3  8,1 としの行列の積です。 #include <stdio.h> int main(void) { int i,j; int ma[2][3] = {{1,2,3},{4,5,6}}; int mb[3][2] = {{1,5},{5,3},{8,1}}; int mc[2][2] = {0}; for(i=0;i<2;i++) for(j=0;j<3;j++) mc[i][i] += ma[i][j]*mb[j][i]; mc[1-i][i] += ma[1-i][j]*mb[j][i]; for(i=0;i<2;i++){ for(j=0;j<2;j++) printf("%3d",mc[i][j]); putchar('\n'); } return(0); } 結果は↓のようになります。 38 0 0 41 まだプログラミングをはじめて日が浅いので基本てきなとこが抜けてる かもしれません。よろしくお願いします。

  • 転置行列 証明 行列の積

    転置行列の証明について疑問点があるので 質問させて頂きます。 t(AB)=t(B)t(A) の証明について。以下に示します。 行列 A の (i,j) 成分を A[i,j] と書くことにします。 行列Bも同様。 (t(AB))[i,j] = (AB)[j,i] = Σ A[j,k] B[k,i] = Σ (tA)[k,j] (tB)[i,k]  …(1) = Σ (tB)[i,k] (tA)[k,j]  …(2) = ((tB)(tA))[i,j] よって、 t(AB) = (tB)(tA) (1)についてよくわかりません。 行列の積は、 (l,m)行列と(m,n)行列の積は(l,n)行列と定義されますが (1)は(m,l)行列と(n,m)行列の積を計算することに ならないのでしょうか? (m,l)行列と(n,m)行列の積は定義されないので等式でつないでは いけないのでは?と考えた次第です。 以上、ご指摘、ご回答よろしくお願い致します。

専門家に質問してみよう