pypy.com/

Python、Unity、FX自動化などを勉強しています。あと、コーラと車も好きです。そこらへんについて、たまに記事を書きます。

C言語で転置行列を計算する(基本演算)

f:id:SaidaTaisei:20220120193506p:plain こんにちは。

今回は、C言語で転置行列を作成する方法を紹介します。

そんなのライブラリとかでやれよってなるかもしれませんが、自分でもかけた方がいいと思うので、やっていきます。

転置行列の考え方

以下のような、m×nの行列Aを考えます。

 
A=\left(\begin{array}{cccc}
a_{11} & a_{12} & \ldots & a_{1 n} \\
a_{21} & a_{22} & \ldots & a_{2 n} \\
\vdots & \vdots & \ddots & \vdots \\
a_{m 1} & a_{m 2} & \ldots & a_{m n}
\end{array}\right)

この時、行列Aの転置行列をBとすると、

 
B=\left(\begin{array}{cccc}
a_{11} & a_{21} & \ldots & a_{m 1} \\
a_{12} & a_{22} & \ldots & a_{m 2} \\
\vdots & \vdots & \ddots & \vdots \\
a_{1 n} & a_{2 n} & \ldots & a_{m n}
\end{array}\right)

となります。

ここで、各要素ごとについて、考えると、以下のようになります。

 
B_{i j}=A_{j i}

ここで、 i,jはそれぞれ行番号と列番号です。

転置行列を作成するC言語コード

特定の行列を転置する

ここでは、以下の行列を転置行列にすることを考えます。

 
A=\left(\begin{array}{ccc}
1 & 1 & 1 \\
2 & 2 & 2 \\
3 & 3 & 3 \\
\end{array}\right)

これの転置行列をBとすると、以下のようになるはずです。

 
B=\left(\begin{array}{ccc}
1 & 2 & 3 \\
1 & 2 & 3 \\
1 & 2 & 3 \\
\end{array}\right)

それでは、プログラムを書いていきます。
プログラムを書くと以下のようになります。

#include <stdio.h>

int main(void){
  // 行列Aの定義
  double A[3][3] = {
    {1,1,1},
    {2,2,2},
    {3,3,3}
  };
  // 行列Aの表示
  printf("Matrix A\n");
  for(int i=0; i<3; i++){
    for(int j=0;j<3;j++){
      printf("%.2lf ",A[i][j]);
    }
    printf("\n");
  }
  // 行列Bの計算
  double B[3][3];
  for(int i=0; i<3; i++){
    for(int j=0;j<3;j++){
      B[i][j] = A[j][i];
    }
  }
  // 行列Bの表示
  printf("\nMatrix B\n");
  for(int i=0; i<3; i++){
    for(int j=0;j<3;j++){
      printf("%.2lf ",B[i][j]);
    }
    printf("\n");
  }
}

これを実行すると、以下のような結果が得られます。

手で計算した結果とあっていることが確認できます。

Matrix A
1.00 1.00 1.00
2.00 2.00 2.00
3.00 3.00 3.00

Matrix B
1.00 2.00 3.00
1.00 2.00 3.00
1.00 2.00 3.00

もっと汎用性の高いプログラム

上で示した方法で、転置行列を求めることができました。

しかし、上の例では、行列のサイズが最初に分かっている必要があります。

もっとどんな行列が入っても、転置行列が得られるようにプログラムを書いてみます。

以下のように書きました。(なんか汚いので、もっときれいに書きたいですね)

#include <stdio.h>
#define COUNTOF(array) (sizeof(array) / sizeof(array[0]))

void transpose_matrix(double *matrix, double *outMat, int size1, int size2);

int main(void){
  // 行列Aの定義
  double A[4][3] = {
    {1,1,1},
    {2,2,2},
    {3,3,3},
    {4,4,4}
  };
  // 行列Aのサイズの取得
  int size1 = COUNTOF(A);     // 行サイズ
  int size2 = COUNTOF(A[0]);  // 列サイズ
  // 行列Aの表示
  printf("Matrix A\n");
  for(int i=0; i<size1; i++){
    for(int j=0; j<size2; j++){
      printf("%.2lf ", A[i][j]);
    }
    printf("\n");
  }
  // 行列Bの初期化
  double B[size2][size1];
  for(int i=0; i<size2; i++){
    for(int j=0; j<size1; j++){
      B[i][j] = 0.0;
    }
  }
  // ポインタ
  double *aMat = (double *)A;
  double *bMat = (double *)B;
  // 転置行列の関数に入力
  transpose_matrix(aMat, bMat, size1, size2);
  // 行列Bの整形
  for(int i=0; i<size2; i++){
    for(int j=0; j<size1; j++){
      B[i][j] = bMat[i*size1 + j];
    }
  }
  // 行列Bの表示
  printf("\nMatrix B\n");
  for(int i=0; i<size2; i++){
    for(int j=0;j<size1;j++){
      printf("%.2lf ", B[i][j]);
    }
    printf("\n");
  }
}

// 転置行列を計算する関数
void transpose_matrix(double *matrix, double *outMat, int size1, int size2){
  for(int i=0; i<size2; i++){
    for(int j=0; j<size1; j++){
      outMat[i*size1 + j] = matrix[j*size2 + i];
    }
  }
}

実行すると、以下のようになります。

Matrix A
1.00 1.00 1.00
2.00 2.00 2.00
3.00 3.00 3.00
4.00 4.00 4.00

Matrix B
1.00 2.00 3.00 4.00
1.00 2.00 3.00 4.00
1.00 2.00 3.00 4.00

これも、手で計算してみると、あっていることが確認できます。

以上で終わります。