このページでは、C言語での「転置行列の求め方」について解説していきます。
C言語での行列の扱い方については下記ページで解説していますので、そもそもC言語で行列を扱う方法をご存知ない方は、事前に下記ページを読んでいただくことをオススメします。
【C言語】行列の扱い方転置行列とは
転置行列は、元々の行列の「行と列を入れ替える」ことで求まる行列のことを言います。
例えば、下記の2行3列の行列 \(A\) において、
$$ A = \left ( \begin{array}{ccc} a_{11} & a_{12} & a_{13} \\ a_{21} & a_{22} & a_{23} \end{array} \right ) $$
行列 \(A\) の転置行列 \({}^t\! A\) は下記の行列となります。
$$ {}^t\! A = \left ( \begin{array}{cc} a_{11}’ & a_{12}’ \\ a_{21}’ & a_{22}’ \\ a_{31}’ & a_{32}’ \end{array} \right ) = \left ( \begin{array}{cc} a_{11} & a_{21} \\ a_{12} & a_{22} \\ a_{13} & a_{23} \end{array} \right ) $$
転置行列を求める際のポイントは2つです。
まず前述の通り、転置行列は元々の行列の「行と列を入れ替える」ことで求まる行列です。
したがって、転置行列の行数と列数は元々の行列のものと反転します。つまり、行列 \(A\) が \(M\) 行 \(N\) 列であれば、転置行列 \({}^t\! A\) は \(N\) 行 \(M\) 列となります。これがポイントの1点目です。
また、行と列を入れ替えるのですから、行列 \(A\) の成分 \(a_{ij}\) と成分 \(a_{ji}\) が入れ替わることになります。
つまり、転置行列 \({}^t\! A\) の \(j\) 行 \(i\) 列の成分 \(a_{ji}’\) は、行列 \(A\) の \(i\) 行 \(j\) 列の成分 \(a_{ij}\) と同じになります。これがポイントの2点目です。
転置行列を求める
ここまでの解説を踏まえると、転置行列を求めるプログラムを実装する際には次のようなことを行なっていく必要があります。
スポンサーリンク
行列を扱う2次元配列を変数宣言する
まず転置行列を求める対象となる行列を扱うための2次元配列を変数宣言します。
今回はこの変数名を mat
、扱う行列の行数を M
、列数を N
とします。
/* 行列扱う2次元配列 */
int mat[M][N];
続いて、転置行列を扱うための2次元配列を変数宣言します。
今回はこの変数名を t_mat
とします。転置行列の行数と列数は、転置行列を求める行列の行数と列数を反転させたものになります。具体的には行数 N
・列数 M
となります。
/* matの転置行列を扱う2次元配列 */
int t_mat[N][M];
転置行列の成分を格納する
あとは、t_mat[j][i]
に mat[i][j]
の値を格納していけば、行列 t_mat
が行列 mat
の転置行列として求まることになります。
/* 転置行列の成分を格納する */
for (i = 0; i < M; i++) {
for (j = 0; j < N; j++) {
/* 行と列を入れ替えた位置に格納 */
t_mat[j][i] = mat[i][j];
}
}
転置行列を求めるプログラムの例
ここまで解説してきた内容に基づいて作成した転置行列を求めるプログラムのソースコード例は下記のようになります。
#include <stdio.h>
#define M 4 /* 転置行列を求める行列の行数 */
#define N 2 /* 転置行列を求める行列の列数 */
int main(void) {
/* 行列扱う2次元配列 */
int mat[M][N];
/* matの転置行列を扱う2次元配列 */
int t_mat[N][M];
int i, j;
/* matの成分の設定 */
mat[0][0] = 1; mat[0][1] = 2;
mat[1][0] = 3; mat[1][1] = 4;
mat[2][0] = 5; mat[2][1] = 6;
mat[3][0] = 7; mat[3][1] = 8;
/* 転置行列の成分を格納する */
for (i = 0; i < M; i++) {
for (j = 0; j < N; j++) {
/* 行と列を入れ替えた位置に格納 */
t_mat[j][i] = mat[i][j];
}
}
/* 行列をそのまま表示 */
printf("行列:\n");
for (i = 0; i < M; i++) {
for (j = 0; j < N; j++) {
printf("%d,", mat[i][j]);
}
printf("\n");
}
printf("\n");
/* 転置行列の表示 */
printf("転置行列:\n");
for (i = 0; i < N; i++) {
for (j = 0; j < M; j++) {
printf("%d,", t_mat[i][j]);
}
printf("\n");
}
return 0;
}
実行すれば、mat
そのものと、mat
の転置行列(t_mat
)の成分が表示されます。
行列: 1,2, 3,4, 5,6, 7,8, 転置行列: 1,3,5,7, 2,4,6,8,
下記を変更すれば、転置行列を求めたい行列の行数や列数を変更可能です。変更後の行数や列数に応じて mat
に格納する必要のある成分の数も変わるので注意してください。
#define M 4 /* 転置行列を求める行列の行数 */
#define N 2 /* 転置行列を求める行列の列数 */
スポンサーリンク
転置行列の表示のみ行う
ここまでの解説では、転置行列用の2次元配列を用意し、その2次元配列に転置行列の成分を格納することで転置行列を求めてきました。
そのため、その2次元配列を利用して転置行列を用いた行列演算などを実行することも可能です。
ただ、転置行列を用いる必要がなく、単に転置行列の表示だけ行いたいのであれば、もっと簡単に実現することができます。
具体的には、下記のソースコードのプログラムにより転置行列の表示を行うことができます。
#include <stdio.h>
#define M 4 /* 転置行列を求める行列の行数 */
#define N 2 /* 転置行列を求める行列の列数 */
int main(void) {
/* 行列扱う2次元配列 */
int mat[M][N];
int i, j;
/* matの成分の設定 */
mat[0][0] = 1; mat[0][1] = 2;
mat[1][0] = 3; mat[1][1] = 4;
mat[2][0] = 5; mat[2][1] = 6;
mat[3][0] = 7; mat[3][1] = 8;
/* 行列をそのまま表示 */
printf("行列:\n");
for (i = 0; i < M; i++) {
/* 1行ずつ表示する */
for (j = 0; j < N; j++) {
printf("%d,", mat[i][j]);
}
printf("\n");
}
printf("\n");
/* 転置行列の表示 */
printf("転置行列:\n");
for (j = 0; j < N; j++) {
/* 1列ずつ表示する */
for (i = 0; i < M; i++) {
printf("%d,", mat[i][j]);
}
printf("\n");
}
return 0;
}
実行すれば、mat
そのものと、mat
の転置行列の成分が表示されます。
行列: 1,2, 3,4, 5,6, 7,8, 転置行列: 1,3,5,7, 2,4,6,8,
mat
そのものの成分を表示する時と mat
の転置行列の成分を表示する時とで異なるのはループの組み方のみです。より具体的には、2重ループの内側のループを j
のループとするか、i
のループとするかの違いがあるのみです。
まず前提として、mat[i][j]
において1つ目の添字 i
は行列の「行」を表す添字となります。さらに、2つ目の添字 j
は行列の「列」を表す添字となります。
したがって、列 j
のループを内側のループとして mat[i][j]
の表示を行えば、i
行目の行が表示されていくことになります。つまり、行単位で行列の成分が表示されることになります。
mat
そのものを表示する際にはコレを利用して行単位で行列の成分を表示しているため、上の行から順に成分が横並びに表示されていくことになります。
なので、mat
が扱う行列の成分の並び順に成分が表示されていくことになります。
その一方で、行 i
のループを内側のループとして mat[i][j]
の表示を行えば、j
列目の列が表示されていくことになります。つまり、列単位で行列の成分が表示されることになります。
mat
の転置行列を表示する際にはコレを利用して列単位で行列の成分を表示しているため、左の列から順に成分が横並びに表示されていくことになります。
なので、mat
が扱う行列の成分が「行と列を入れ替えた形」で成分が表示されていくことになります。
こんな感じで2重ループで2次元配列の要素を表示する場合、内側のループと外側のループを入れ替えるだけで転置行列を表示するようなことも可能です。逆に言えば内側のループと外側のループが逆になるだけで表示される結果が意図しないものになってしまいます。
2次元配列の要素を表示する際には1次元配列の場合よりも考慮すべき点が多いので、この点は注意してください。
まとめ
このページでは、C言語での「転置行列の求め方」について解説しました!
単に行と列を入れ替えれば良いだけなので、考え方はかなり簡単だと思います。
ただ、実際に実装してみると結構頭が混乱するんじゃないかなぁと思います…。少なくとも私は苦手かな…。行列そのものを扱う2次元配列と逆行列を扱う2次元配列では行数と列数が反転するので、この辺りがややこしいかなぁと思います。
例えば 転置行列を求めるプログラムの例 で紹介したソースコードでは、M
は mat
を扱う上では行数を表すのに対し、t_mat
を扱う上では列数を表すことになり、同じ定数が別の意味になってしまってややこしいです。
なので t_mat
の行数と列数を表す定数は mat
の行数と列数を表す定数とは別のものとして定義してあげたほうがソースコードは書きやすくなるかもしれないですね…。
こんな感じで、転置行列を求めるプログラムを実装してみることで転置を実現する上での複雑さを実感することができ、それを解決するにはどうソースコードを記述すれば良いかを考えるきっかけにもなると思います。2次元配列にも慣れることもできますので、是非一度は転置行列を求めるプログラムの作成に挑戦してみてください!