質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.48%
C

C言語は、1972年にAT&Tベル研究所の、デニス・リッチーが主体となって作成したプログラミング言語です。 B言語の後継言語として開発されたことからC言語と命名。そのため、表記法などはB言語やALGOLに近いとされています。 Cの拡張版であるC++言語とともに、現在世界中でもっとも普及されているプログラミング言語です。

Q&A

解決済

1回答

1357閲覧

行と列が違う配列の掛け算

kamecha

総合スコア41

C

C言語は、1972年にAT&Tベル研究所の、デニス・リッチーが主体となって作成したプログラミング言語です。 B言語の後継言語として開発されたことからC言語と命名。そのため、表記法などはB言語やALGOLに近いとされています。 Cの拡張版であるC++言語とともに、現在世界中でもっとも普及されているプログラミング言語です。

0グッド

0クリップ

投稿2017/10/13 15:16

###前提
書籍で勉強している学生です。
書籍の2周目をしています。
書籍の解答がないため問題のヒントや解説をしていただけると嬉しいです。

###問題
4行3列の行列と3行4列の行列の積を求めるプログラムを作成せよ。
各構成要素の値はキーボードから読み込むこと。

###該当のソースコード

lang

1 2 /*各配列の要素を掛け合わせる*/ 3 4 int l = 0; 5 for(i = 0; i < 2; i++){ 6 for(j = 0; j < 3; j++){ 7 sum[l] = x[i][j]; 8 l++; 9 } 10 } 11 12 int k = 0; 13 for(i = 0; i < 3; i++){ 14 for(j = 0; j < 2; j++){ 15 sum[k] = sum[k] * y[i][j]; 16 k++; 17 } 18 }

###疑問点
各構成要素の値を掛け合わせる時に、現在大きな二つのfor文を使用しているのですが。
これを一つにすっきりとまとめる方法があれば教えていただきたいです。

###補足情報
書籍 : 新明解C言語 入門編
演習 5-10

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答1

0

ベストアンサー

行列の積を計算するためには、各要素の値を内積として計算する必要があります。
ですので、率直に組むと三重ループとなります。

C = A*B とすると、次のような感じです。

C

1for(int row = 0; row < A_row; row++) { 2 for(int col = 0; col < B_col; col++) { 3 for(int i = 0; i < A_col; i++) { 4 C[row][col] += A[row][i] * B[i][col]; 5 } 6 } 7}

ただし、Cの要素は0に初期化されているとします。
デバッグしていないのでちょっとしたミスがあったらごめんなさい。

おまけ

楽しそうなので自分なりに書いてみました。
あまり参考にならないかもしれませんが、せっかく作ったので載せておきます。

main.c

C

1#include "matrix.h" 2#include <stdlib.h> 3 4#define SIZE(array) sizeof(array) / sizeof(array[0]) 5 6int main(int argc, char **argv) { 7 MATRIX matrix_a, matrix_b, matrix_c; 8 9 int raw_a[][3]= { 10 { 3, 0, 5}, {-1, 5, 7}, { 1, 6, -3}, { 6, 3, 2} 11 }; 12 make_matrix(&raw_a[0][0], SIZE(raw_a), SIZE(raw_a[0]), &matrix_a); 13 14 int raw_b[][4]= { 15 { 3, 1, 2, 3}, { 2, 4, 2, 6}, {-3, 3, 0, 1} 16 }; 17 make_matrix(&raw_b[0][0], SIZE(raw_b), SIZE(raw_b[0]), &matrix_b); 18 19 int raw_c[m_row(&matrix_a)][m_col(&matrix_b)]; 20 make_matrix(&raw_c[0][0], m_row(&matrix_a), m_col(&matrix_b), &matrix_c); 21 compute_matrix_product( 22 &matrix_a, &matrix_b, &matrix_c 23 ); 24 25 print_matrix_w_info(&matrix_a); 26 print_matrix_w_info(&matrix_b); 27 print_matrix_w_info(&matrix_c); 28 29 return EXIT_SUCCESS; 30}

vector.h

C

1#include <stdlib.h> 2 3int compute_inner_product( 4 const int *vector_a, const int *vector_b, size_t len 5); 6 7void print_vector(const int *vector, size_t len);

vector.c

C

1#include "vector.h" 2#include <stdio.h> 3#include <stdlib.h> 4 5void print_vector(const int *vector, size_t len) { 6 for(size_t i = 0; i < len; i++) { 7 printf("%4d ", vector[i]); 8 } 9 printf("\n"); 10} 11 12int compute_inner_product( 13 const int *vector_a, const int *vector_b, size_t len) 14{ 15 int sum = 0; 16 for(size_t i = 0; i < len; i++) { 17 sum += vector_a[i] * vector_b[i]; 18 } 19 return sum; 20}

matrix.h

C

1#include <stdlib.h> 2 3#define BUFFER_LEN 100 4#define print_matrix_w_info(matrix) \ 5 print_matrix_w_info_(#matrix, matrix) 6 7typedef struct { 8 int *value_; 9 size_t row_; size_t col_; 10} MATRIX; 11 12MATRIX *make_matrix( 13 int *value, size_t row, size_t col, MATRIX *dst 14); 15MATRIX *input_matrix(MATRIX *dst); 16 17const int * m_value(const MATRIX *matrix); 18const size_t m_row (const MATRIX *matrix); 19const size_t m_col (const MATRIX *matrix); 20 21int value_at (const MATRIX *matrix, size_t row, size_t col); 22int set_value_at( MATRIX *matrix, size_t row, size_t col, int value); 23 24int *make_horizontal_vector_from_matrix_row( 25 const MATRIX *matrix, int *dst, int row_num 26); 27int *make_vertical_vector_from_matrix_col( 28 const MATRIX *matrix, int *dst, int col_num 29); 30 31MATRIX *compute_matrix_product( 32 const MATRIX *matrix_a, const MATRIX *matrix_b, 33 MATRIX *dst 34); 35 36void print_matrix(const MATRIX *matrix); 37void print_matrix_w_info_(const char *name, const MATRIX *matrix);

matrix.c

C

1#include "vector.h" 2#include "matrix.h" 3 4#include <stdio.h> 5#include <stdlib.h> 6#include <string.h> 7 8MATRIX *make_matrix( 9 int *value, size_t row, size_t col, MATRIX *dst) 10{ 11 dst->value_ = value; 12 dst->row_ = row; 13 dst->col_ = col; 14 15 return dst; 16} 17MATRIX *input_matrix(MATRIX *dst) { 18 char buffer[BUFFER_LEN]; 19 20 printf("%d x %d\n", m_row(dst), m_col(dst)); 21 for(size_t row = 0; row < m_row(dst); row++) { 22 fgets(buffer, BUFFER_LEN, stdin); 23 24 int num = atoi(strtok(buffer, " ")); 25 for(size_t col = 0; col < m_col(dst); col++) { 26 set_value_at(dst, row, col, num); 27 num = atoi(strtok(NULL, " ")); 28 } 29 } 30 return dst; 31} 32 33const int * m_value(const MATRIX *matrix) { return matrix->value_; } 34const size_t m_row (const MATRIX *matrix) { return matrix->row_; } 35const size_t m_col (const MATRIX *matrix) { return matrix->col_; } 36 37int value_at(const MATRIX *matrix, size_t row, size_t col) { 38 return m_value(matrix)[row*m_col(matrix) + col]; 39} 40int set_value_at(MATRIX *matrix, size_t row, size_t col, int value) { 41 matrix->value_[row*m_col(matrix) + col] = value; 42} 43 44int *make_horizontal_vector_from_matrix_row( 45 const MATRIX *matrix, int *dst, int row_num) 46{ 47 for(size_t col = 0; col < m_col(matrix); col++) { 48 dst[col] = value_at(matrix, row_num, col); 49 } 50 return dst; 51} 52int *make_vertical_vector_from_matrix_col( 53 const MATRIX *matrix, int *dst, int col_num) 54{ 55 for(size_t row = 0; row < m_row(matrix); row++) { 56 dst[row] = value_at(matrix, row, col_num); 57 } 58 return dst; 59} 60 61MATRIX *compute_matrix_product( 62 const MATRIX *matrix_a, const MATRIX *matrix_b, 63 MATRIX *dst 64) { 65 int *work_row_vec = (int *)malloc(sizeof(int) * m_col(matrix_a)); 66 int *work_col_vec = (int *)malloc(sizeof(int) * m_row(matrix_b)); 67 68 for(size_t row = 0; row < m_row(matrix_a); row++) { 69 for(size_t col = 0; col < m_col(matrix_b); col++) { 70 make_horizontal_vector_from_matrix_row( 71 matrix_a, work_row_vec, row 72 ); 73 make_vertical_vector_from_matrix_col( 74 matrix_b, work_col_vec, col 75 ); 76 77 set_value_at( 78 dst, row, col, compute_inner_product( 79 work_row_vec, work_col_vec, m_row(matrix_b) 80 ) 81 ); 82 } 83 } 84 85 free(work_row_vec); 86 free(work_col_vec); 87 return dst; 88} 89 90void print_matrix(const MATRIX *matrix) { 91 int work[m_col(matrix)]; 92 for(size_t row = 0; row < matrix->row_; row++) { 93 print_vector( 94 make_horizontal_vector_from_matrix_row( 95 matrix, work, row 96 ), m_col(matrix) 97 ); 98 } 99} 100void print_matrix_w_info_(const char *name, const MATRIX *matrix) { 101 if(name[0] == '&') name++; 102 printf("%s\n", name); 103 104 if(matrix->value_ == NULL) { 105 printf("Matrix is not initialized\n"); 106 } 107 else { 108 print_matrix(matrix); 109 } 110 111 printf("row->%d / col->%d\n", m_row(matrix), m_col(matrix)); 112 printf("\n"); 113}

実行結果

matrix_a 3 0 5 -1 5 7 1 6 -3 6 3 2 row->4 / col->3 matrix_b 3 1 2 3 2 4 2 6 -3 3 0 1 row->3 / col->4 matrix_c -6 18 6 14 -14 40 8 34 24 16 14 36 18 24 18 38 row->4 / col->4

たまにCに触れると楽しいです。
ランタイムエラーへの対策ががばがばなのはご愛嬌です。
実際にはmallocの返り値や標準入力をチェックした方が丁寧でしょう。

投稿2017/10/13 20:19

編集2017/10/14 04:37
LouiS0616

総合スコア35660

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

kamecha

2017/10/14 10:31

このmatrix.hはご自分で作られたのですか? ヘッダを自作できるとは、知らなかったので…
LouiS0616

2017/10/14 10:48

平たく言えば、ヘッダは『プロトタイプ宣言をまとめたもの』です(だいぶ語弊はある)。 ヘッダをインクルードすることで、関数を任意のタイミングで使えるようにしているのです。
LouiS0616

2017/10/14 10:51

私の書いたコードは、ポインタを取りまわしていたり、構造体をオブジェクト指向的に用いていたりするので、初心者にはちょっと高度な内容だと思います。 『なんか、こんな感じでも書けるんだなぁ』と思うくらいで大丈夫です。
kamecha

2017/10/14 11:10

よっ良かった… 自分にとって高度だったので、後々理解できるように頑張ります。
LouiS0616

2017/10/14 11:14

頑張ってくださいね。 この手の演算は面倒なので、実用する際には普通既存のライブラリを使います。 逆に言うと学習目的以外では自作することはあまりないので、ちょっと楽しんでしまいました。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問