ガウス・ジョルダン法の専用の関数を作る場合,どうするか?.まず,その入 出力と機能を考える.入力は,係数行列の と非同次項の が必要である. そして,出力は逆行列の と解のベクトル となる. 要するに,図1のような機 能の関数をつくるわけである.
この関数ができると,問題を解く時に必要な係数行列と非同次項を入力さえす れば,逆行列と解を計算してくれる.ガウス・ジョルダン 法の手続きを,関数で実現する方法について,次節以降で丁寧に説明する.
いかなるプログラム言語でも,C言語の関数(mainではない)に対応するものが有り,それ は,サブルーチンと呼ばれている.同じような処理がある場合,1つの独立した処理のブ ロックとしてまとめ,どこからでもコールすることができるようにすると便利である.こ のような,機能のブロックをサブルーチンと呼ぶ.例えば,sin(x)などである. の計算が必要な都度,その処理を書いていたのではたまらないので,独立した関 数としてその処理が書くのである.これは,ライブラリーとなっているので,その処理内 容は通常は分からない.
この関数に,データを与える変数のことを引数と言う.先ほどの例で言うと, sin(x)のxが引数である.プログラムの中では,sinと言う 名前がついている処理にxを与え,それを処理する.
引数には,2種類(実引数と仮引数)が有る.それについて,次のプログラムで説明する. この場合,main関数でコールするときの文,add(x,y)のxと yを実引数と呼ぶ.そして,その処理を書いている関数add(double xin, double yin)のxinとyinを仮引数という.呼ぶ方の変数を実引 数,呼ばれる方の変数を仮引数と呼ぶのである.
#include <stdio.h> double add(double xin, double yin); /* ========== main関数 =================*/ main(){ double x, y, wa; いろいろな処理 wa=add(x,y); いろいろな処理 } /* ========== 足し算の関数 =================*/ double add(double xin, double yin){ double zout; zout = xin+yin; return(zout); }
実引数から仮引数に値を送る方法は,C言語では2通りの方法がある.以前学習した通りで,
C言語の場合,通常の変数(配列でない)の場合,値渡しである.これは良くできた仕様で ある.処理する関数が呼び出し側のデータを変えることが無いので,プログラミングの時, 余計な気を使わないですむ.関数の独立性が高いといわれる所以である.実際の例では, 先のaddという関数は,main関数から呼び出されており,main の実引数の値(x,y)の値が,addの仮引数(xin,yin)にコピー される.そこでの処理の結果は,戻り値(返却値)zoutに入れられて,元の関数 に戻す.元の関数のwaに,zoutの値がコピーされるのである.
一方,配列を処理する関数に渡す場合は,アドレス渡しになる.一般に配列のデータは, 通常の変数よりもかなり大きく,それをいちいちコピーしていたら不経済ということが理 由と言われている.
ということで,今回の場合,配列を渡すためアドレス渡しになる.処理する関数でその配 列の値を変えると,コールした関数のその値も変わる.しかし,これは便利なこともある. いちいち戻り値を与える必要が無く,気軽に呼び出した関数に結果を戻せる(FORTRANと同 じ).
従って,図1のような入出 力の関数を実現するための引数の書き方は,
#include <stdio.h> void gaussjordan(double a[][100], double b[100], double inv_a[][100], double x[100]); /* ========== main関数 ==============================================*/ void main(){ double a[100][100], b[100]; double inv_a[100][100], x[100]; いろいろな処理 gaussjordan(a,b,inv_a,x); いろいろな処理 } /* ========== ガウスジョルダン法の関数 =============================*/ void gaussjordan(double a[][100], double b[100], double inv_a[][100], double x[100]){ いろいろな処理 inv_a[i][j] = いろいろな計算 b[i] = これも計算 いろいろな処理 }
となる.処理する関数の方は,一番最初のサイズを除いて書く必要がある.これは,例え ばz[100][200][300]の大きさの配列のz[23][73][36]というデータに アクセスする場合を考えれば分かる.このデータがあるアドレスは,[Zのアド レス+配列1個のデータサイズ ]になる. したがって,最初の配列のサイズを除いて,配列のサイズがアドレス計算に必要となり, 処理する関数側で明示する必要がある.
実際のプログラムでは,もう少し効率よく配列を使うが,大筋はこの通り である.これで,関数に値を与える復習は終わり.
int gaussjordan(int n, double a[][100], double b[100], double inv_a[][100], double x[100]);