- ベストアンサー
行列の計算
2行3列のマトリクスAと3行2列のマトリクスBの各要素(整数)をキーボードから読み込み、 C=A×BとなるマトリクスCを計算するプログラムを作りたい。 ただ、配列を使用せずに読み込み・計算・出力で作らなくてはなりません。 (まだ配列の勉強をしていないので…) a11 a12 A= a21 a22 A31 a32 b11 b12 b13 B= b21 b22 b23 C=? 参考書などで調べたところ int main( void ) { int i, j; double a[3][3] = { { 1, 2, 1 }, { 3, 4, 3 }, { 1, 2, 1 } }; double b[3][3] = { { 1, 2, 3 }, { 1, 1, 1 }, { 3, 2, 1 } }; double c[3][3]; for( i = 0 ; i < 3 ; i++ ){ for( j = 0 ; j < 3 ; j++ ){ c[i][j] = a[i][j] + b[i][j]; } } } のようなものがでてきました。 数字を変え、+を*にしてやってみたのですが、うまくいきませんでした。 また、a11のような数字は認識しませんでした。 プログラム初心者で理解するのに時間がかかるかもしれませんが、 どなたかアドバイスお願いします。
- namisem
- お礼率89% (66/74)
- C・C++・C#
- 回答数6
- ありがとう数8
- みんなの回答 (6)
- 専門家の回答
質問者が選んだベストアンサー
まず、文章と例が違っていますが・・ 2行3列のマトリクスAとあるのに、例は3行2列。 同様にBも行と列が逆になっています。 さらに、「配列を使用せず・・」とあるにもかかわらず、 a[3][3] などの配列を使用していますね。 仮に3×2の行列Aと2×3の行列Bを考えると、 求める行列Cは3×3になりますから、 配列を使用しないのであれば、 int a11, a12, a21, ・・・; int b11, b12, b13, ・・・; int c11, c12, c13, ・・・; として、aとbそれぞれに対して数字をキーボードから入力。 全ての入力が終わったら、cの計算をします。 c11 = a11 * b11 + a12 * b21; c12 = a11 * b12 + a12 * b22; ・ ・ 配列を使ってよいならば、 int a[3][2]; int b[2][3]; int c[3][3]; for( i = 0; i < 3; i++ ){ /* aの行数回す */ for( j = 0; j < 3; j++ ){ /* bの列数回す */ c[i][j] = 0; for( k = 0; k < 2; k++ ){/* aの列数回す */ c[i][j] += a[i][k] * b[k][j] } } } でOKのはずです。
その他の回答 (5)
- Euglena
- ベストアンサー率62% (5/8)
c11 = a11 * b11 + a12 * b21; は、 右辺(a11 * b11 + a12 * b21)の計算結果を 左辺(c11)に代入するということなので、 このままの記述でc11に結果が格納されます。 想定範囲内の入力値が全て入力されるのであれば、 提示されたものでいいと思います。 ・int型の範囲を超えた数値が入力されたら? ・入力がなかったら? ・計算結果が範囲を超えたら? ・間違い入力を訂正させるには? ・もうちょっとスマートに・・ などいろいろ考えていけば、それが力になると思います。 語句の意味や説明などは、参考書やmurasaki_rocksさんが書かれている方法などで調べてみてください。
お礼
回答ありがとうございます。 やっと、何とかできました。 c11 = a11 * b11 + a12 * b21; もそのままでよかったです。 原因はそのあとの printf("%d",c11); のc11が入っていませんでした。 うっかりミスです… 色々試してもっと自分の力になるように頑張ります。 ありがとうございました
- murasaki_rocks
- ベストアンサー率18% (7/37)
技術系は人から教えられているのもいいのですがそれではその人以上の技術を身に付けられないし、状況環境に応じた技術が必要です。 その為、参考になるサイトは特に紹介しませんが、 探す際の簡単なキーワードをあげときますので自力で探してください。 検索するサイト http://www.google.co.jp/ キーワード int long 等は 型といいます。 for switch等は 制御構文といいます。 printf 等は ライブラリ関数といいます。
お礼
回答ありがとうございます。 >技術系は人から教えられているのもいいのですがそれではその人以上の技術を身に付けられないし、状況環境に応じた技術が必要です そうですね。 すみません。頼りすぎていたと思います。 もっと自分から調べて、知識を増やしたいです。 用語も調べてみます。 ありがとうございました。
- murasaki_rocks
- ベストアンサー率18% (7/37)
えーと。 >ただ、配列を使用せずに読み込み・計算・出力で作らなくてはなりません。 >double A[2][3] = { { a11,a12}, >{ a21, a22, a31 }, >{ a31, a32 } }; これって世間一般では配列って言いませんか? ちなみに整数ならintかlongでしょ。
お礼
回答ありがとうございます。 すみません、勘違いしていました。 配列を使わずになので、ひとつひとつ c11=a1*b11+a12*b21 のようにして決めていかなければならないみたいです…。 あとintを使うようです。 もう少し考えて見ます。
- ranx
- ベストアンサー率24% (357/1463)
>> 3重ループの計算をする必要があると思います > とはどういうことでしょうか? こういうことです。 for( i = 0 ; i < 3 ; i++ ){ for( j = 0 ; j < 3 ; j++ ){ C[i][j] = 0; for( k = 0 ; k < 2 ; k++ ){ C[i][j] += A[k][j] * B[i][k]; } } }
お礼
再びありがとうございます。 どうやら勘違いしていたみたいです。
- ranx
- ベストアンサー率24% (357/1463)
aとbを3行3列の配列にするから錯覚するのです。 条件通り、3行2列・2行3列にすれば、ループの 制御変数が合わないことに気がつくはずです。 3重ループの計算をする必要があると思います。
お礼
回答ありがとうございます。 int main( void ) { int i, j; double A[2][3] = { { a11,a12}, { a21, a22, a31 }, { a31, a32 } }; double B[3][2] = { {b11, b12, b13 }, { b21, b22, b23 }}; double C[3][3]; for( i = 0 ; i < 3 ; i++ ){ for( j = 0 ; j < 3 ; j++ ){ C[i][j] = A[i][j] * B[i][j]; } のようにしてやってみたのですが、できませんでした。 >3重ループの計算をする必要があると思います とはどういうことでしょうか? 質問ばかりですみません。
関連するQ&A
- 行列の計算について。
こんにちは。 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
- 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; }
- ベストアンサー
- C・C++・C#
- 行列に関して。
以下の行列を対角成分が最も大きくなるような プログラムをつくりたいのですが 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 です。
- 締切済み
- C・C++・C#
- 行列の計算
#include<stdio.h> #define N 2 #define M 3 void hyoji(float[][M]); int main(){ int i,j,k; float a[N][M] = {{2.0,2.0,2.0},{2.0,2.0,2.0}}; float b[M][M] = {{1.0,1.0,1.0},{2.0,2.0,2.0},{1.0,1.0,1.0}}; float c[N][N]; for(i=0; i<N; i++){ for(j=0; j<M; j++){ c[i][j] = 0; for(k=0; k<M; k++){ c[i][j] += a[i][k] * b[k][j]; } } } hyoji(c); return(0); } void hyoji(float x[][M]){ int i,j; for(i=0; i<N; i++){ for(j=0; j<M; j++){ printf("%4.1f ",x[i][j]); } printf("\n"); } } 以上のプログラムで 行列aと行列bをかけ合せた行列cを求めるのですが コンパイルすると 8 8 8 8 8 1 となり、正しい結果がでません。 なにが間違っているのでしょうか?? よろしくお願いします。
- 締切済み
- C・C++・C#
- 行列の積を関数を使って求める・・?
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・C++・C#
- 行列の積について
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・C++・C#
- 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]); } }
- 締切済み
- その他(プログラミング・開発)
- 初心者な質問その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を使って下の行列を計算するプログラム についてお願いします。
- 締切済み
- C・C++・C#
- 行列の積を計算するプログラムがうまくいきません
どこが間違っているのかわかる方お願いします ・行列A,Bはファイルから読み込む ・行列A,Bの積Cの計算には関数を用いる #include<stdio.h> #define ROW 10 #define COL 10 void MatrixProduct(int a[][COL],int b[][ROW],int c[][ROW],int n,int m ) { int i,j,k; for(i=0;i<n;i++){ for(j=0;j<n;j++){ c[i][j]=0; } } for(i=0;i<n;i++){ for(j=0;j<n;j++){ for(k=0;k<m;k++){ c[i][j]=c[i][j]+a[i][k]*b[k][j]; } } } } int main(void) { FILE *fp1,*fp2; char fname1[64],fname2[64]; int a[ROW][COL],b[ROW][COL],c[ROW][COL],n,m; int i,j,k; printf("Input file name ?"); scanf("%s",fname1); printf("Output file name ?"); scanf("%s",fname2); fp1=fopen(fname1,"r"); fp2=fopen(fname2,"w"); fscanf(fp1,"%d %d",&n,&m); MatrixProduct(a,b,c,n,m); for(i=0;i<n;i++){ for(j=0;j<n;j++){ fprintf(fp2,"%3d",c[i][j]); } fprintf(fp2,"\n"); } fclose(fp1); fclose(fp2); return(0); } fp1 3 4 1 2 3 4 2 3 4 5 3 4 5 6 1 2 3 2 3 4 3 4 5 4 5 6
- ベストアンサー
- C・C++・C#
お礼
回答ありがとうございます。 すみません、配列の勘違いをしていました。 配列を使わずになので c11=a1*b11+a12*b21 のようにして決めていかなければならないみたいです。 それと int や scanf、printf、for、swhitch の簡単な意味が知りたいのですが、もし良ければ補足お願いします。わかりやすいサイトでもいいので… 何度もすみません。
補足
途中までできました。 int main(void) { int a11,a12,a21,a22,a31,a32; int b11,b12,b13,b21,b22,b23; int c11,c12,c13,c21,c22,c23,c31,c32,c33; printf("2行3列のマトリクスA\n"); printf(" a11 a12 \n"); printf("A= a21 a22 \n"); printf(" a31 a32 \n"); printf("と、3行2列のマトリクスB\n"); printf(" b11 b12 b13 \n"); printf("B= b21 b22 b23 \n"); printf("から、C=A×B となるマトリクスCを求めたい\n"); printf("a11を入力してください\n"); scanf("%d",&a11); printf("a12を入力してください\n"); scanf("%d",&a12); printf("a21を入力してください\n"); scanf("%d",&a21); printf("a22を入力してください\n"); scanf("%d",&a22); printf("a31を入力してください\n"); scanf("%d",&a31); printf("a32を入力してください\n"); scanf("%d",&a32); printf("b11を入力してください\n"); scanf("%d",&b11); printf("b12を入力してください\n"); scanf("%d",&b12); printf("b13を入力してください\n"); scanf("%d",&b13); printf("b21を入力してください\n"); scanf("%d",&b21); printf("b22を入力してください\n"); scanf("%d",&b22); printf("b23を入力してください\n"); scanf("%d",&b23); このあとに c11=a11*b11+a12*b21 c12=a11*b12+a12*b22 … と入れたいのですが、このときには何を使えばいいのでしょうか?scanfだと変な感じなのですが…