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

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

ただいまの
回答率

89.21%

多次元正方行列の積を求めたい

解決済

回答 4

投稿 編集

  • 評価
  • クリップ 0
  • VIEW 601

h_proc

score 52

正方行列の積を求めるコードを書いています。dt1,dt2,dt3という三つの正方行列を用意して、dt3にdt1×dt2の結果が入力されるようにしました。この時dt3には、{{11,14},{18,23}}が入るはずですが、{{15,20}{24,31}}となってしまいます。どこが間違っているのでしょうか。教えていただきたいです。
また、ついでの質問になってしまうのですが、n次正方行列のnは#define ARRAY_SIZE 2の定義方法(2の部分をその都度変えていく)であっているのでしょうか。また、その時の初期化はどのように行えばよいのでしょうか。
よろしくお願いいたします。

#include <stdio.h>

#define ARRAY_SIZE 2

int doub(int dt1[ARRAY_SIZE][ARRAY_SIZE], int dt2[ARRAY_SIZE][ARRAY_SIZE], int dt3[ARRAY_SIZE][ARRAY_SIZE]);

int doub(int dt1[ARRAY_SIZE][ARRAY_SIZE], int dt2[ARRAY_SIZE][ARRAY_SIZE], int dt3[ARRAY_SIZE][ARRAY_SIZE]) {

    for (int i = 0; i < ARRAY_SIZE; i++) {
        for (int j = 0; j < ARRAY_SIZE; j++) {
            for (int k = 0; k < ARRAY_SIZE; k++) {

                dt3[i][j] += dt1[i][k] * dt2[k][j];

            }
        }
    }
    return dt3[ARRAY_SIZE][ARRAY_SIZE];
}

int main(void)
{
    int dt1[][ARRAY_SIZE] = { {1,2},{2,3} };
    int dt2[][ARRAY_SIZE] = { {3,4},{4,5} };
    int dt3[][ARRAY_SIZE] = { {0,0},{0,0} };

        doub(dt1, dt2, dt3);

    printf("dt1×dt2=\n");

    for (int i = 0; i < ARRAY_SIZE; i++) {
        for (int j = 0; j < ARRAY_SIZE; j++) {
            printf("%3d", dt3[i][j]);
        }
        printf("\n");
    }

    return 0;
}
  • 気になる質問をクリップする

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

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

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 過去に投稿した質問と同じ内容の質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

質問への追記・修正、ベストアンサー選択の依頼

  • namnium1125

    2019/01/05 17:28

    間違えていないようですが...?( https://wandbox.org/permlink/AIsHWvEHxdFkb02i )実行時の詳しい情報等がもう少し欲しいですm(_ _)m

    キャンセル

  • h_proc

    2019/01/05 18:32

    すみません。私のミスでした。正しく実行されました。ありがとうございます。

    キャンセル

  • episteme

    2019/01/05 21:16

    doub の戻り値は何を返したいのかしら? 返すもんがないなら void でええよ。

    キャンセル

  • h_proc

    2019/01/06 07:34

    そうでした。返り値は毎回つけないといけないと思い込んでいました。ありがとうございます。

    キャンセル

回答 4

checkベストアンサー

+2

質問文のコードでも {{11,14},{18,23}} になるようですが、
すこし書き換えてみました。
mat.c

#include <stdio.h>

#define ARRAY_SIZE 2

void doub(int dt1[ARRAY_SIZE][ARRAY_SIZE], int dt2[ARRAY_SIZE][ARRAY_SIZE], int dt3[ARRAY_SIZE][ARRAY_SIZE]) {
  for (int i = 0; i < ARRAY_SIZE; i++) {
    for (int j = 0; j < ARRAY_SIZE; j++) {
      dt3[i][j] = 0;
      for (int k = 0; k < ARRAY_SIZE; k++) {
    dt3[i][j] += dt1[i][k] * dt2[k][j];
      }
    }
  }
}

int main(void)
{
  int dt1[][ARRAY_SIZE] = { {1,2},{2,3} };
  int dt2[][ARRAY_SIZE] = { {3,4},{4,5} };
  int dt3[][ARRAY_SIZE] = { {0,0},{0,0} };

  doub(dt1, dt2, dt3);

  printf("dt1×dt2=\n");

  for (int i = 0; i < ARRAY_SIZE; i++) {
    for (int j = 0; j < ARRAY_SIZE; j++) {
      printf("%3d", dt3[i][j]);
    }
    printf("\n");
  }
  return 0;
}

実行例
イメージ説明

ARRAY_SIZE は行列の列数になってます。
doub で dt1[ARRAY_SIZE][ARRAY_SIZE] のようにしているので。

追記
2x2, 3x3 の行列も扱えるようにしてみたものを示します。

#include <stdio.h>

void doub(int n, int dt1[][n], int dt2[][n], int dt3[][n]) {
  for (int i = 0; i < n; i++) {
    for (int j = 0; j < n; j++) {
      dt3[i][j] = 0;
      for (int k = 0; k < n; k++) {
    dt3[i][j] += dt1[i][k] * dt2[k][j];
      }
    }
  }
}

void show_matrix(int n, int dt[][n]) {
  for (int i = 0; i < n; i++) {
    for (int j = 0; j < n; j++) {
      printf("%3d", dt[i][j]);
    }
    printf("\n");
  }
}

int main(void)
{
  int dt2_1[2][2] = { {1,2},{2,3} };
  int dt2_2[2][2] = { {3,4},{4,5} };
  int dt2_3[2][2] = { {0,0},{0,0} };

  doub(2, dt2_1, dt2_2, dt2_3);
  show_matrix(2, dt2_3);
  printf("\n");

  int dt3_1[3][3] = { {1,2,3},{2,3,0},{0,0,1} };
  int dt3_2[3][3] = { {3,4,0},{4,5,0},{0,0,1} };
  int dt3_3[3][3];

  doub(3, dt3_1, dt3_2, dt3_3);
  show_matrix(3, dt3_3);

  return 0;
}

実行例
イメージ説明

投稿

編集

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2019/01/06 07:41

    ありがとうございます。最初のコードのままで、ARRAY_SIZE 3にする方法でも3次の計算は可能でしょうか。

    キャンセル

  • 2019/01/06 07:48

    > ... 最初のコードのままで、ARRAY_SIZE 3 ...
    ご自分で試してみてください。
    その上で問題・疑問がでたら、その詳細をお知らせください。

    キャンセル

  • 2019/01/06 07:59

    そうですね。やってみます。聞いてばかりですみません。

    キャンセル

+2

こちらでコピペしてそのまま実行させたら、

dt1×dt2=
11 14
18 23

とでましたね
# VisualStudio2017community


んでついでに、

    return dt3[ARRAY_SIZE][ARRAY_SIZE];

動作には関係ないですが、なにげに範囲外アクセスになってますね

投稿

編集

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2019/01/05 18:24

    範囲外アクセスとはどういうことでしょうか。このreturnは不要ですか。何もわかっていなくて、申し訳ありません。

    キャンセル

  • 2019/01/05 20:11

    dt3 の定義は、
    int dt3[ARRAY_SIZE][ARRAY_SIZE]
    となってますが、これは、
    dt3[0~ARRAY_SIZE-1][0~ARRAY_SIZE-1]
    までの範囲でしか領域の想定はされてません
    ってことで、
    dt3[2][2]
    の読み出しは範囲外となります

    #まあ、読み出しだけなら不具合はなさそうですが

    キャンセル

  • 2019/01/06 07:36

    そうなんですね。全然知りませんでした。ありがとうございます。
    ARRAY_SIZE 3にすれば有効になるということでしょうか。

    キャンセル

  • 2019/01/06 08:14 編集

    いや多分元コードのままでは範囲外アクセスのままですよ…(dt3[3][3]にアクセスしてますので)

    まぁ元から要らない返り値に関する話題ですが()

    返り値が不要であること(と範囲外アクセスであったこと)以外に元コードに問題はなかったように感じます。

    キャンセル

+1

本質ではないですけど、dt3をゼロ行列で初期化しておかないと積関数の結果が合いませんよ。

まあ、初期化を関数の前でやれば良いのですが。

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

0

動的に次元を変更して計算させたいなら、malloc関数を使用して配列を動的に確保するか、予め大きめに配列を確保しておくという方法があります。

後者のほうが比較的楽です。

以下コード例

#include <stdio.h>
#include <stdlib.h>
#define ARRAY_MAX_SIZE 256
#define MEM 256 // 入出力用の定数ですので気にしないでください。

// 入力用関数

char* input(char* str, char* desc) {
    printf(desc);
    fgets(str, MEM, stdin);
    return str;
}

void doub(int dt1[ARRAY_MAX_SIZE][ARRAY_MAX_SIZE],
        int dt2[ARRAY_MAX_SIZE][ARRAY_MAX_SIZE],
        int dt3[ARRAY_MAX_SIZE][ARRAY_MAX_SIZE],
        int dim) { // dim は dimention の略
    for (int i = 0; i < dim; i++) {
        for (int j = 0; j < dim; j++) {
            dt3[i][j] = 0; // 追加
            for (int k = 0; k < dim; k++) {
                dt3[i][j] += dt1[i][k] * dt2[k][j];
            }
        }
    }
}

int main(void) {
    int
        dt1[ARRAY_MAX_SIZE][ARRAY_MAX_SIZE],
        dt2[ARRAY_MAX_SIZE][ARRAY_MAX_SIZE],
        dt3[ARRAY_MAX_SIZE][ARRAY_MAX_SIZE];

    char str[MEM];
    int dim = atoi(input(str, "dim? : "));


    // 入力

    printf("dt1\n");
    for (int i = 0; i < dim; i++) {
        for (int j = 0; j < dim; j++) {
            printf("i:%d j:%d : ", i, j);
            dt1[i][j] = atoi(input(str, ""));
        }
    }

    printf("dt2\n");
    for (int i = 0; i < dim; i++) {
        for (int j = 0; j < dim; j++) {
            printf("i:%d j:%d : ", i, j);
            dt2[i][j] = atoi(input(str, ""));
        }
    }

    // 計算

    // doub(dt1, dt2, dt3);
    doub(dt1, dt2, dt3, dim);

    // 出力

    printf("dt1 * dt2=\n");

    for (int i = 0; i < dim; i++) {
        for (int j = 0; j < dim; j++) {
            printf("%d ", dt3[i][j]);
        }
        printf("\n");
    }

    return 0;
}

入出力例:

$ ./tera
dim? : 2
dt1
i:0 j:0 : 1
i:0 j:1 : 2
i:1 j:0 : 2
i:1 j:1 : 3
dt2
i:0 j:0 : 3
i:0 j:1 : 4
i:1 j:0 : 4
i:1 j:1 : 5
dt1 * dt2=
11 14
18 23

投稿

編集

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2019/01/05 19:27 編集

    コンパイルしなおすのが億劫なのだと仮定して回答しましたが、そうでないならば質問者様の方法も普通にアリだと思いますよ。

    キャンセル

  • 2019/01/05 23:42

    dt3[i][j] = 0;という処理を忘れておりましたので追記しておきました。

    キャンセル

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

  • ただいまの回答率 89.21%
  • 質問をまとめることで、思考を整理して素早く解決
  • テンプレート機能で、簡単に質問をまとめられる

同じタグがついた質問を見る