ログインしてさらにmixiを楽しもう

コメントを投稿して情報交換!
更新通知を受け取って、最新情報をゲット!

C言語とC++言語コミュの行、列の異なる掛け算

  • mixiチェック
  • このエントリーをはてなブックマークに追加
助けてください(>_<)
再々々履修中です…

今日参考書を読んでいて答えを見てもよくわからない問題が合ったので誰がわかりやすく教えてくれませんか?
問題:2行3列と3行2列の行列の積を求める

ソース:
#include <stdio.h>
int main (void)
{
int i,j,k;
int mx[2][3]={{1,2,3},{4,5,6}};
int my[3][2]={{1,5},{5,3},{8,1}};
int mz[2][2]={0};

for(i=0;i<2;i++){
for(j=0;j<2;j++){
mz[i][j]=0; /*疑問?
   for(k=0;k<3;k++)
mz[i][j] +=mx[i][k]*my[k][j];/*疑問?
}
}

for(i=0;i<2;i++){
for(j=0;j<2;j++)
printf("%3d",mz[i][j]);
putchar('\n');
}

return(0);

}


/*疑問というところがわかりません。
?mz[i][j]=0;
と置く理由 またなんで0?
?mz[i][j] +=mx[i][k]*my[k][j];
の式の意味
そもそも行、列が異なる掛け算の仕方がわかりません(苦笑)

実行結果は
35 14
77 41
になります!!!

コメント(25)

最初の疑問は配列の初期化だと思いますよ。

2つ目の疑問は掛けたものを足していくΣ計算をしています。行列の積の計算の仕方を考えてみてください。そうするとわかると思います
プログラムの前に行列の勉強が必要ですね。
行列の積の計算がわからないのでは、
プログラムを解読することも難しいと思います。
というか無理でしょう・・・
単純に「+=」の意味が分かれば?も?も解決だと思いますね。

・ mz[i][j]=0;の行を入れない
・ 疑問?の行の前後でmzの値をアウトプットしてみる
・ 線形代数学入門の本を読む

きっとこれで解決
寧ろ
int mz[2][2]={0};
の方が気になります。
どうせやるなら
int mz[2][2]={0,0,0,0};

ですよね・・・。
?をやるならどうでも良いか。
みなさんありがとうございます!!
mz[i][j]=0;の行を入れなくても平気なんですね(>_<)行列の計算の仕方を学びみなさんのヒントでわかりました!!
mz[i][j] = mz[i][j] + (mx[i][k] * my[k][j]) を導き出させたので…
これで応用になって応用に対応できるように訓練していきたいと思います…
>>11
前者は20個全部0になり
後者は最初の1つしか0にしてない。
gccなら
int a[2][5] = { 0 };

.globl a
        .bss
        .align 32
        .type   a, @object
        .size   a, 40
a:
        .zero   40
初期化子の要素を省略した場合は残りの要素を0で埋めることになってたと思うんですが、違いました?
 Cの場合、広域変数や静的変数は0で初期化されています。しかし、スタック上に取られる自動変数は、領域の確保をするだけで、明示的に初期化しないと、初期化は行われません。

int     array[3][3];
         memset( array, 0x00, sizeof(array));

 Cならこんな書き方もできます。
 C++で、これはやら無いほうが安全です。(intなら問題がないけど、classだったりすると、思わぬ目にあいます
 
> 明示的に初期化しないと、初期化は行われません。

1. int a[2][5]; // 明示的に初期化しない
2. int a[2][5] = {0}; // 頭だけzero初期化
3. int a[2][5] = {0,0,0,0,0,0,0,0,0,0}; // 全てzero初期化

今は2が3の代用になるかという話であって、
1は脈絡ないです。
> ふぃりすさん
合ってると思います。
少なくともISO C++では初期化が省略された要素は0クリアされたはず。
なので表記はどちらでもいいのですが、単に2回初期化してるのが気になっただけです(^^;

たっくりんさんとsock/vuelaさんのコードはグローバル変数かスタティック変数かで配列を作ったコードだと思いますが、ローカル変数の場合スタックを0クリアするコードを埋め込まれるので、結構な無駄になると思います。

93さんはmz[i][j]=0;を外す方を選択したようですが、僕だったら最初の配列の初期化を外すかなぁ。
#include <iostream>
int main()
{
int a[4] = { 0 };
int b[4];
for(size_t i = 0; i < sizeof(a) / sizeof(a[0]); i++)
std::cout << "a[" << i << "]=" << a[i] << std::endl;
for(size_t i = 0; i < sizeof(b) / sizeof(b[0]); i++)
std::cout << "b[" << i << "]=" << b[i] << std::endl;
return 0;
}

g++だと、aは4つとも0を出力、bは4つとも0以外の値を出力。
> たっくりんさん
C/C++でのDATAセグメントの初期化はスタートアップコード(crt0など)で行われてます。main関数が呼ばれる前です。
開発環境によっては手動で初期化関数を呼ばないといけないというのもありますが・・・

ログインすると、残り11件のコメントが見れるよ

mixiユーザー
ログインしてコメントしよう!

C言語とC++言語 更新情報

C言語とC++言語のメンバーはこんなコミュニティにも参加しています

星印の数は、共通して参加しているメンバーが多いほど増えます。

人気コミュニティランキング