行列の積を計算するEXCELマクロ
M×Lの行列とL×Nの行列の積を計算するExcelマクロを作成する。
Excelのワークシートの任意の場所に下図のようにデータ(一番上に行列の大きさを指示するM,L,
N、続けて積を求める2つの行列の値)を入力し、Mを記したセルをアクティブにして実行したとき、
1行空白行を空けて結果(積)を出力するマクロを作成する。データ個数がどのようなものであっても
同様に出力できるようにする。
|
M L N
↓ ↓ ↓
|
第1行列3×4 →
第2行列4×5 →
結果の出力先 →
|
3 | 4 |
5 | |
| |
1 | 2 |
3 | 4 |
| |
5 | 6 |
7 | 8 |
| |
9 | 0 |
1 | 2 |
| |
1 | 2 |
3 | 4 |
5 | |
6 | 7 |
8 | 9 |
0 | |
1 | 2 |
3 | 4 |
5 | |
6 | 7 |
8 | 9 |
0 | |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
|
(1) MとLとNを読み込む。Mを読み込み、アクティブセルを右に移動させてL、さらに右に移動させ
てNを読み込む。
M = ActiveCell
ActiveCell.Offset(0, 1).Range("A1").Select
L = ActiveCell
ActiveCell.Offset(0, 1).Range("A1").Select
N = ActiveCell
(2) VBにおいては、配列(行列と同じ)は用意されておらず、使用するときに定義しなければならな
い。第1行列をA、第2行列をB、結果の行列をCを名付けることにする。このとき、配列の定義は
次のようになる。
ReDim A(M, L), B(L, N), C(M, N)
(3) 行列Aを読み込むプログラムは次のようになる。
ActiveCell.Offset(1, -2).Range("A1").Select
For i = 1 To M
For j = 1 To L
A(i, j) = ActiveCell
ActiveCell.Offset(0, 1).Range("A1").Select
Next j
ActiveCell.Offset(1, -L).Range("A1").Select
Next i
第1行目は、アクティブセルがNを読み込んだ場所にあるので、行列の左上隅に移動させる命令であ
る。3行目から6行目は、行の先頭にアクティブセルがあるときに、読んで右移動を繰り返すための
ものである。7行目は、1行分のデータを読み終わった後で、次の行に先頭にアクティブセルを移動
させる命令である。2行目と8行目は、必要な行数分だけ繰り返すための命令である。
(4) 行列Bを読み込むプログラムは次のようになる。
For i = 1 To L
For j = 1 To N
B(i, j) = ActiveCell
ActiveCell.Offset(0, 1).Range("A1").Select
Next j
ActiveCell.Offset(1, -N).Range("A1").Select
Next i
行列Aを読み込むときとの違いは、Aを読み終わったとき、アクティブセルが行列Bの左上隅にある
ことと、読み込む個数及び移動する個数が異なっていることのみである。
(5) 行列AとBの積Cを求める。行列Cのi-j要素C(i, j)は、Aの第i行とBの第j列の要素それぞ
れの積の総和である。すなわち
C(i, j) = A(i, 1)*B(1, j) + A(i, 2)*B(2, j) + ・・・ + A(i, L)*B(L, j)
である。これを計算するプログラムは
s = 0
For k = 1 To L
s = s + A(i, k) * B(k, j)
Next k
C(i, j) = s
となる。ここで、sの代わりに C(i, j) を用いれば最後の行が不要であるが、記述を簡単化するた
めにsを用いている。C全体を求めるためには、上のプログラムのiを1からMへ、jを1からNへ
変化させればよい。したがって、次のようになる。
For i = 1 To M
For j = 1 To N
s = 0
For k = 1 To L
s = s + A(i, k) * B(k, j)
Next k
C(i, j) = s
Next j
Next i
(6) 結果を出力する。現在のアクティブセルの位置は、空白行の先頭であるので、出力先の左上隅にア
クティブセルを移動させる。
ActiveCell.Offset(1, 0).Range("A1").Select
行列の出力は、読み込みの逆であり、行毎に出力して右移動を繰り返し、必要なだけ行出力を繰り返
せばよい。結果は次のようになる。
For i = 1 To M
For j = 1 To N
ActiveCell = C(i, j)
ActiveCell.Offset(0, 1).Range("A1").Select
Next j
ActiveCell.Offset(1, -N).Range("A1").Select
Next i
M×L1行列A、L1×L2行列B、L2×N行列Cの積、すなわちA・B・CをDに計算するプログラムは次
のようになる。複雑であるが、各自で確認してみてもらいたい。
For i = 1 To M
For j = 1 To N
s = 0
For k1 = 1 To L1
For k2 = 1 To L2
s = s + A(i, k1) * B(k1, k2) * C(k2, j)
Next k2
Next k1
D(i, j) = s
Next j
Next i
|