###前提
書籍で勉強している学生です。
書籍の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ページで確認できます。
またクリップした質問に回答があった際、通知やメールを受け取ることができます。
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
回答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総合スコア35660
あなたの回答
tips
太字
斜体
打ち消し線
見出し
引用テキストの挿入
コードの挿入
リンクの挿入
リストの挿入
番号リストの挿入
表の挿入
水平線の挿入
プレビュー
質問の解決につながる回答をしましょう。 サンプルコードなど、より具体的な説明があると質問者の理解の助けになります。 また、読む側のことを考えた、分かりやすい文章を心がけましょう。
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
2017/10/14 10:31
2017/10/14 10:48
2017/10/14 10:51
2017/10/14 11:10
2017/10/14 11:14