• 検索結果がありません。

interface 文

ドキュメント内 Fortran (2015 ) (ページ 64-69)

第 3 章 サブルーチン 37

3.8 プログラミング スマートテクニック ( その 3)

3.8.5 interface 文

Fortranは古くからある言語なので,文法的にゆるい記述がいくつか残っています22.implicit none を付けなければ暗黙の変数宣言と見なされ,宣言しなくても変数が自由に使えるというのはその一つで す.これ以外に,サブルーチンを呼び出すためのcall文の記述において引数のチェックをしない,と いう問題があります.このため,call文で引数の数を間違えたり引数の数値型を間違えたりしてもコン パイルエラーにはならず,実行時に正常な動作をしないという形で不具合が現れます.

この欠点を補うため,最近のFortranでは,interface文を使ってプログラム中に外部副プログラ ムの引数の形状を宣言しておき,外部副プログラムを使用する際の引数チェックをコンパイラにさせ ることができます.interface文は,interfaceend interfaceではさんだブロックで,その中に subroutine文またはfunction文,その引数宣言(関数副プログラムの場合は関数値も),および最後の end文だけを取り出して入れておきます.例えば,3.8.4節のサブルーチンsubroutや関数funを使用 する場合,以下のように書くことができます.

22キーボードやモニターがなかった時代,プログラムを書くのは時間がかかる作業でした.このため,記述量を減らすため に暗黙の宣言などがあったのだと思います.C言語は比較的新しい言語なので,変数宣言は必ず行わなければならないし,関 数の引数チェック機能も含まれています.

program test_interface implicit none

external sub interface

subroutine subrout(subr,xmin,xmax,n)

external subr ! 外部副プログラムはexternal文で宣言する

real xmin,xmax integer n

end subroutine subrout function fun(x)

real fun,x ! 関数の場合は関数値も宣言する

end function fun end interface

call subrout(sub,0.0,3.0,10)

! call subrout(0.0,3.0,10) ! これを入れるとエラーになる

print *,fun(10.0)

! print *,fun(10) ! これを入れるとエラーになる

end program test_interface

この例のように,interface文中には複数のサブルーチンや関数副プログラムの宣言を書くことができ ます.また,interface文中に関数副プログラムの宣言を入れておくと,関数名の型宣言が入っている ので,その関数名の型宣言を別途する必要はなくなります.なお,外部副プログラムを引数にする場合 には,この例のようにexternal文で宣言しておきます.

このプログラム例で,二つ目のsubroutcall文を含めてコンパイルするとエラーになります.な ぜなら,二つ目のcall文は引数の数が足らず,一番左の引数が外部副プログラムではなく実数になっ ているからです.また,二つ目の関数funを使用したprint文を含めてもエラーです.これは,xが実 数指定なのに整定数10を与えているからです.

interface文で引数の型を宣言しておくと,引数変数に値を代入した形でサブルーチンをコールする

ことができます.この場合,引数を記述する順番は自由です.例えば,

program test_interface implicit none

external sub integer m interface

subroutine subrout(subr,xmin,xmax,n) external subr

real xmin,xmax integer n

end subroutine subrout end interface

m = 5

call subrout(n=m**2,subr=sub,xmax=3.0,xmin=0.0) end program test_interface

と書くことができます.

ただし,3.5節において,「配列名を引数にすることと,その配列の第1要素を引数にすることは同じ意 味になる」と言いましたが,interface文を使う場合は区別する必要があります.なぜなら,interface 文は引数の型だけでなく形状のチェックも行うからです.このため,interface文中の宣言が1変数で あれば1変数か定数を,1次元配列で宣言したならば1次元配列名を,というように引数の形状と一致し た変数や配列をcall文の引数に与えなければなりません.さもなくば,コンパイルエラーになります.

interface文を使うと,より安全なプログラムになります.大きなプログラムを作る時や,引数が多い

サブルーチンを利用するときは,interface文の利用をお勧めします.必要な部分だけをコピー・ペー ストするだけなので,それほど手間はかかりません.

演 習 問 題 3

(3–1) 2次方程式の解 (サブルーチン利用) 3個の実変数abcを引数とし,それから,

ax2+bx+c= 0 の2x1x2,および判別式D=

b24acを計算して戻り値にするサブルーチンを作成せよ.ただ し,2実解になる場合は,x1x2をそれぞれ戻り値変数x1x2に代入し,2虚解になる場合は,実部 をx1に,虚部をx2に代入するようにせよ.

次にそれを使って問題(2–6)の解答をサブルーチンを使う形に修正せよ.

(3–2) ヘロンの公式 (関数副プログラム利用)

三角形の三辺の長さをabcとすると,その三角形の面積Sは次式(ヘロンの公式)で表される.

S =√

p(p−a)(p−b)(p−c) ただし,p= a+b+c

2 である.

abcの数値を引数とし,この公式を使って三角形の面積を計算して関数値にする関数副プログラ ムを作成せよ.

次にそれを使って問題(1–2)の解答を関数副プログラムを使う形に修正せよ.

(3–3) 回路計算 (サブルーチン利用)

N 個の抵抗R1, R2, R3,· · · , RNに対し,このN個を直列にした時の合成抵抗RsN 個を並列にし た時の合成抵抗Rpを同時に計算して戻り値として返すサブルーチンを作成せよ.ただし,N 個の抵抗 値は,要素数n1次元配列R(n)で表すとする.

次に,それを使って問題(1–7)の解答をサブルーチンを使う形に修正せよ.

(3–4) 3次元ベクトルと電磁気学 (サブルーチン利用)

3次元ベクトルA= (A1, A2, A3)を要素数3の1次元配列a(3)で表すとする.電場ベクトルE,磁 場ベクトルBおよび荷電粒子の速度ベクトルvを配列で表して,これらの配列を引数として与えると内 積vE,および外積ベクトルv×Bを計算して戻り値とするサブルーチンを作成せよ.なお戻り値の 外積ベクトルも配列とする.これを使って問題(1–8)の解答をサブルーチンを使う形に修正せよ.

(3–5) 統計計算 (サブルーチン利用) 要素数nの1次元配列,a(n)を引数とし,

平 均 A=¯ 1 n

n i=1

Ai

標準偏差 σ= vu ut1

n

n i=1

(Ai−A)¯ 2

を計算して戻り値とするサブルーチンを作成し,問題(2–2)の解答をサブルーチンを使う形に修正せよ.

(3–6) 非線形方程式の解法:Newton法 (サブルーチン利用)

問題(2–8)のNewton法を用いて方程式の解を計算するプログラムをサブルーチンを使う形に修正せ

よ.まず,変数値xを与えると関数値f(x)とその微分値f0(x)を返すようなサブルーチンを作成する.

それを使ってNewton法で解を求めるプログラムにすればよい.

(3–7) 行列計算

nn列の行列aij を2次元配列a(n,n)の要素a(i,j)で表すとする.2個の行列aijbij から行列 の和,cij,および行列の積,dijを計算するサブルーチンを作成せよ.この時,整合配列を用いて与える 配列の次元が自由に変えられるようにすること.

ここで,行列の和と積の定義は以下の通りである.

cij =aij+bij

dij =

n k=1

aikbkj

(3–8) 行列式

u(3),v(3),w(3)という3つの1次元配列データから行列式

Det=

u(1) v(1) w(1) u(2) v(2) w(2) u(3) v(3) w(3)

を計算する関数副プログラムを作成せよ.

(3–9) 3元連立方程式の解法 31次の連立方程式,

a11x1+a12x2+a13x3 =b1 a21x1+a22x2+a23x3 =b2

a31x1+a32x2+a33x3 =b3 を解くプログラムのサブルーチンを作成せよ.

クラメールの公式によれば,答えは以下のようになる.

x1 =

b1 a12 a13 b2 a22 a23

b3 a32 a33

D , x2=

a11 b1 a13 a21 b2 a23

a31 b3 a33

D , x3 =

a11 a12 b1 a21 a22 b2

a31 a32 b3

D ただし,

D=

a11 a12 a13

a21 a22 a23

a31 a32 a33 である.

プログラムは,33列の行列aij を2次元配列a(3,3)の要素a(i,j)で表し,biをb(i)という1 元配列で表し,xiをx(i)という1次元配列で表して,サブルーチンの引数は,abxとする.行列 式の計算には,問題 で作成した関数副プログラムを利用すればよい.

(3–10) モンテカルロ法

世の中の動きは,運動方程式のような微分方程式を用いて確実に予測できるとは限らない.例えば,

さいころを投げて次にどの数字が出るかで進み方を決めるすごろくのように,次の瞬間に何が起こるか わからない事象を元にして未来の様子を計算する方法をモンテカルロ法という.

計算機でさいころの代わりをするものは“乱数と呼ばれている.Fortranには,サブルーチン

random_numberが用意されているので,これを用いれば乱数を使った計算ができる.例えば,1個の乱

数を使うときには

call random_number(x)

と書けば,変数xに05x <1の範囲の実数が代入される.このサブルーチンの戻り値xは予測がつか ないので,同じ呼び出しを繰り返しても、それ以前に代入された値と等しい数値が代入される確率は非 常に小さい.

乱数を1回で複数用意したいときには配列を使う.例えば,配列a(10)10個の乱数を代入すると きは次のように書けばよい.

call random_number(a(1:10))

モンテカルロ法を使って円周率πを計算してみよう.2個の乱数xyを発生させて2次元座標点

(x, y)を作る.この乱数の座標点をN個作り,その中で原点から半径1の円より内側にある点の数N1

を数えてp= 4N1

N を計算する.座標点数N が増えると,このpπに近づくことを確かめよ.

ドキュメント内 Fortran (2015 ) (ページ 64-69)