バナナでもわかる話

計量経済学・統計学が専門の大学院生です。統計学・経済学・投資理論・マーケティング等々に関する勉強・解説ブログ。ときどき趣味も。極力数式は使わずイメージで説明出来るよう心掛けていますが、時々暴走します。

C++で行列の演算を行う関数を書いてみた

最近C++で数値計算が行えるよう練習中です。

スポンサーリンク



今回は、配列から行列を作って、足し算、引き算、内積を計算するコードを書いてみました。
うーん。一応出力は正しい値が出ていますが、もっと綺麗なコードを書きたい。
まあ、C++の勉強始めて少ししか経っていないので、これから頑張ります笑

ちなみに参考本はこちら

#include "pch.h"
#include <iostream>
//行列サイズ
#define N 2
#define M 3

とりあえず前回のベクトルと同様行列の次元の定義。

更に、クラスを定義して、行列の表示、足し算、引き算、内積を計算するメンバ関数を作ってみました。

class Matrix {
	float ma[N][M];
	float mb[N][M];
	float mc[M][N];
	float Plu_res[N][M];
	float Minus_res[N][M];
	float IProd_res[N][N];

public:
	void PrintMa(float ma[N][M]){
		cout << "行列を表示する" << endl;
		for (int j = 0; j < N; j++) {
			cout << endl;
			for (float *jj = begin(ma[j]); jj != end(ma[j]); jj++) {
				cout << *jj<< ",";
			}
		}
		cout << endl;
	}

	void PlusMa(float ma[N][M], float mb[N][M],float Plu_res[N][M]) {
		for (int j = 0; j < N; j++) {
			float *bb = begin(mb[j]);
			float *cc = begin(Plu_res[j]);
			for (float *jj = begin(ma[j]); jj != end(ma[j]); jj++) {
				*cc = *jj + *bb;
				bb++;
				cc++;
			}
		}
	}

	void MinusMa(float ma[N][M], float mb[N][M], float Minus_res[N][M]) {
		for (int j = 0; j < N; j++) {
			float *bb = begin(mb[j]);
			float *cc = begin(Minus_res[j]);
			for (float *jj = begin(ma[j]); jj != end(ma[j]); jj++) {
				*cc = *jj - *bb;
				bb++;
				cc++;
			}
		}
	}

	void IProdMa(float ma[N][M], float mc[M][N], float IProd_res[N][N]) {
		for (int j = 0; j < N; j++) {
			float kari1[M];
			for (int mm = 0; mm < M; mm++) {
				kari1[mm] = ma[j][mm];
			}
			int num = 0;
			for (float *jj = begin(IProd_res[j]); jj != end(IProd_res[j]); jj++) {
				float kari2[M];
				for (int mm = 0; mm < M; mm++) {
					kari2[mm] = mc[mm][num];
				}
				*jj = 0;
				for (int mmm = 0; mmm < M; mmm++) {
					*jj = *jj + kari1[mmm] * kari2[mmm];
				}
				num++;

			}
		}
	}
};

各メンバ関数の説明をしていくと
PrintMa関数:引数にN行M列の配列を取り、行列っぽく出力します。
PlusMa関数:次元の等しい二種類の行列を入れて、結果を入れる配列を用意すると、行列の足し算をしてくれます
MinusMa関数:PlusMa関数の引き算バージョン。先にいれた配列から後にいれた配列を引く
IProdMa関数:二種類の行列の内積を取ります。結果を入れる配列も用意しておきます。

IProdMaあたり、メチャメチャゴチャゴチャしていてアレですね。
自分で書きながら、絶対もっと簡単な方法あるなあ....なんて思いました笑


さて、出力を見てみることにします。

まず、行列を表示させてみます。

int main()
{
	Matrix MM;
	float mB[N][M] = { {2,3,3},{5,2,4} };
	float mmB[N][M] = { {2,5,3},{3,7,5} };
	float mmmB[M][N] = { {2,4},{3,1},{5,8} };
	float mat_res[N][M] = { {0,0,0},{0,0,0} };
	float mat_res2[N][N];
	//行列の表示
	MM.PrintMa(mB);
}

出力結果

行列を表示する

2,3,3,
5,2,4,


内積も出してみます。内積については、N行N列の結果が出てくるので、PrintMaの引数の配列をそれ用に変えてからだしました。

	//行列の内積
	MM.IProdMa(mB, mmmB, mat_res2);
	MM.PrintMa(mat_res2);

出力結果

行列を表示する

28,35,
36,54,

おーうまくいっとる。一応出力出来た~けど、コードはどう見ても汚いですね~~~うーむ。お手本がほしい。