C 言語サンプルプログラム (行列の積)

-- 目次 --

  1. 前書き
  2. プログラム

1. 前書き

ここでは正方行列の積を求めるプログラムを与えます。 どこにでも書かれているありふれたものです。

内容は角度が 2π/100 ラジアンの回転行列を 100 乗してディスプレーに 表示するものです。 従って、単位行列に非常に近い行列が表示されるはずです。

1. プログラム

matrix.c

#include <stdio.h>
#include <math.h>

#define N 2
#define Pi 3.14159

void Mul(double x[][N], double y[][N], double z[][N]);
void Copy(double x[][N], double y[][N]);
void Display(double x[][N]);


void main(){
    double x[N][N] = {{1.0,0.0},{0.0, 1.0}}, a[N][N], c[N][N];
    int i;

    a[0][0] = cos(2 * Pi/100);   a[0][1] = - sin(2 * Pi/100);
    a[1][0] = sin(2 * Pi/100);   a[1][1] =   cos(2 * Pi/100);

    for(i = 0; i<100; i++){
        Mul(x, a, c);
        Copy(c, x);
    }

    Display(x);

}

void Mul(double x[][N], double y[][N], double z[][N]){
    int i,j,k;

    for(i = 0; i<N; i++){
        for(j = 0; j<N; j++){
            z[i][j] = 0.0;
            for(k = 0; k<N; k++){
                z[i][j] = z[i][j] + x[i][k] * y[k][j];
            }
        }
    }
}

void Copy(double x[][N], double y[][N]){
    int i,j;

    for(i = 0; i<N; i++){
        for(j = 0; j<N; j++){
            y[i][j] = x[i][j];
        }
    }
}

void Display(double x[][N]){
    int i, j;
    
    for(i = 0; i<N; i++){
        for(j = 0; j<N; j++){
            printf("%f ", x[i][j]); 
        }
        printf("\n");
    }

}

簡単な説明

math.h

3 角関数、指数関数などの数学関数を使用するには、math.h を インクルードしなければいけません。 プログラムではサイン sin、コサイン cos を使用しています。なお三角関数の角度の単位はラジアンです。

#define

ソースファイルのヘッダーで


#define N 2

とすると、コンパイラーがコンパイルの時点で、ソースファイル中の N を 2 で置き換えます。 この行には、改行を意味するセミコロンが付いていないことに注意してください。 #include <stdio.h> にもセミコロンが付いていませんが、 これらはすべてコンパイラーに対する指示で、プログラム本体ではないためです。

高次元配列


    float a[3][3], c[3][3];
    double x[3][3] = {{1.0,0.0},{0.0, 1.0}};
    int y[3][4][5]; 

のようにすれば、高次元配列が定義できます。上の場合の 2 番目の例のようにすれば、 配列を宣言すると同時に初期化することもできます。 例えば x[3][3] で定められる配列は実メモリー上では


x[0][0], x[0][1], x[0][2], x[1][0], x[1][1], x[1][2], x[2][0], ...
 

のように一列にならんでおり、宣言と同時に初期化する場合には 各列を大括弧でくくって表示します。

高次元の配列を C 関数に手渡すためには、プロトタイプ宣言で


void Mul(double x[][N], double y[][N], double z[][N]);

のように、2 番目以後の添字の大きさを指定します。 実メモリー上では、1 次元配列と区別がつかないため、 区切りの位置を指定する必要があるためです。