みその計算物理学
ホーム はじめに リンク集
行列の掛け算の数値計算例(C言語)
  • 行列の掛け算

    行列の掛け算をコンピュータで行うとき、プログラムソースは簡単には書けない。C言語の場合、普通の整数等はアスタリスク * を使って簡単に書いて計算が行えるが行列ではそうはいかない。プログラム中1回行列の掛け算を行うのであればそうでもないが、特に何回も行列の掛け算を行うとすると、そのたびに1から行列の掛け算を行うプログラムソースを書いては、効率が悪いしプログラムソースが長くなってしまう。そこで行列の掛け算を行う関数プロトタイプを定義しておくと便利である。ではさっそく作ってみよう。

  • 行列掛け算の仕組み

    まず3行3列の行列 A と B があるとしよう。また各行列の値を例えば行列 A の1行2列の成分を A12 と表記する。行列 A と B を掛けた結果の行列の1行2列の値は次のように書ける。

    A11XB12+A12XB22+A13XB32

    ここで行列 A の成分は列数、行列 B の成分は行数の番号が 1→2→3 というふうに増加していっている。一方結果の行列の値の成分の行数は行列 A の行数、列数は行列 B の列数と一致している。これらに注目すれば後はC言語の場合 for を使えば簡単にプログラムソースが書ける。

  • 任意の行数列数の正方行列の掛け算の値を求めるプログラム例

    ここでは配列を行列に見立てて計算を行うが特に行列の掛け算を行う関数が受け取る引数について注目してもらいたい。

    #include <stdio.h>
    
    #define N 3
    
    void matrixmultiply(double a[N][N],double b[N][N],double c[N][N]);
    
    int main()
    {
            int i,j;
            double A[N][N],B[N][N],C[N][N];
    
    //計算を行う行列の値を格納する。
            for(i=0;i<N;i++) {
                    for(j=0;j<N;j++) {
                            A[i][j]=B[i][j]=i+j;
                            C[i][j]=0.0;
                    }
            }
    
            matrixmultiply(A,B,C);          //関数を呼び出し行列の掛け算を行う。
    
    //結果を表示する。
            for(i=0;i<N;i++) {
                    for(j=0;j<N;j++) {
                            printf("%f ",C[i][j]);
                    }
                    printf("\n");
            }
    
            return 0;
    }
    
    //掛け算を行う行列2つと、結果を入れる行列を引数として受け取る。
    void matrixmultiply(double a[N][N],double b[N][N],double c[N][N])
    {
            int i,j,k;
    
    //受け取った2つの行列の掛け算を行う。
            for(i=0;i<N;i++) {
                    for(j=0;j<N;j++) {
                            for(k=0;k<N;k++) {
                                    c[i][j]+=a[i][k]*b[k][j];
                            }
                    }
            }
    }
    

    結果は次のようになる。

    5.000000 8.000000 11.000000
    8.000000 14.000000 20.000000
    11.000000 20.000000 29.000000

    確かに計算結果は正しい。

    ここで行列の掛け算を行う関数が特に値を返してもなく、計算結果を格納する配列 C に計算結果が代入されていることに注意したい。普通の整数等の変数を関数が受け取ってその関数内でその変数に代入等しても、元々の変数は影響を受けない。これは、このときは関数が変数を受け取ったときに、新たな変数を格納する場所をメモリーに作るからである。

    しかし、配列を関数に渡す場合は、その配列が存在するメモリーの位置としての情報を関数に渡すのである。よって、当然関数内で受け取った配列を操作すれば、操作した後の情報がそのメモリーの位置に上書きされるので元々の配列の情報は失われる。よって関数に配列を渡すときは注意しておこう。