こんにちは。ざわかける!のざわ(@zw_kakeru)です。
今回は行列についてのお話です。
二次行列はすぐに「あれ、どっちが行でどっちが列だったっけ?」となります。
なぜいつまで経っても覚えられずにすぐに分からなくなるのかという理由の説明と、じゃあどうすれば分からなくならないかを丸覚えではない方法で理解できるように書いてきます。
はじめに
行列って難しいんですよね。
例えば今ここに4×3行列がありますと言われて、どのような形の行列なのかすぐに思い浮かべられるでしょうか。
このような形の行列が4×3行列となります。(4行3列行列と言ったりもします。)
3×4行列とすぐに分からなくなりますね。
こちらが3×4行列です。
すぐ分からなくなる原因
なぜ人類はすぐに「どっちが行でどっちが列なのか」が分からなくなるのでしょうか。
答えは、「縦と横を見る順番が、直交座標の逆だから」です。
直交座標というのは中学生や高校生の時に勉強した、いわゆるxy座標です。
この直交座標の場合、要素(座標)を見る順番は横(x)、縦(y)となります。
すなわち、例えば座標(2, 1)と言われたら、
横に2進み、縦に1進んだ場所が座標(2, 1)となります。
座標以外でもよく出てくるのは、ImgやCanvas形式のデータなどです。
この場合は左上が原点となりますが見る順番は同じで、横、縦です。
一方で行列の場合はこれが逆になり、要素を縦、横の順番で見にいきます。
すなわち、要素(2, 1)と言われたら、
縦に2進み、横に1進んだ要素ということになります。
直交座標の逆なんだということ、だからこそ頭の中でごっちゃになるんだよということを覚えておくだけでかなり楽になるはずです。
解釈の仕方
プログラミングをかじったことがある人はもっと実用的な覚え方が可能です。
どの言語でもいいので、二次配列を思い浮かべてみてください。
例えばC#であれば二次配列は
int matA[,] = new int[4][3] { { 1, 2, 3}, // 4x3行列
{ 4, 5, 6,},
{ 7, 8, 9,},
{10, 11, 12}
};
int matB[,] = new int[3][4] { { 1, 2, 3, 4}, // 3x4行列
{ 5, 6, 7, 8},
{ 9, 10, 11, 12}
};
このように書けますね。
行列はプログラミングと密接な関係があり、行列の定義の仕方は二次配列と同じなのでとても簡単で覚えやすいです。
例えば上記の4×3行列の要素(2, 1)は、と言われたら普通に添字アクセスでmatA[2][1]と書けば良いだけです。
ここだけ見るととても素直ですね。
間違えないようにするには
プログラミングをやっていると直交座標を行列成分に落とし込んだり、その逆に行列成分を直交座標に直したりする場面に出くわす人もいるかもしれません。
どっちがどっちか混乱してしまう人は、ユーティリティ関数を作成してあげましょう。
例えばこんな感じです。
Map.Get(int x, int y) = _marray[y][x]
配列を優先するならこんな感じになりますね。
Map.Get(int y, int x) = _marray[x][y]
ユーティリティ関数を一つ作るだけで、以降はどっちがどっちが気にすることなく記述していくことがあります。
ただし配列処理している関係上、メモリアクセスの順番などによって処理速度が大きく異なる場合があります。
そこまで考慮に入れて変換を行うのであれば、インデックスの指定方法に一工夫が必要になるかもしれませんね。
おわりに
人類というのは、ルールをただルールとして覚えているだけではいつまで経っても頭に記憶することはできません。
どちらが行でどちらが列なのか。
なぜいつもこんがらがるのか、理由と一緒に理解して、さらに二次配列とも結びつけることでもう間違えることは無くなるでしょう。
以上です。