研究室で使われている数値モデルがFORTRAN77で書かれているので、せっかくなのでモデルのソースコードに登場する文法を中心にまとめることにしました(ほとんど自分用ですが...)。今回はFORTRAN77の基本文法に着目して記述していきます。
#文のルール
FORTRAN77の文構造は変数を宣言したりメモリを確保したりする非実行文と演算やファイル入出力を行う実行文とに分かれる。また、大文字と小文字の区別がないので、例えばA,aはどちらも同じ文字としてコンパイラには解釈されます。区別がないといっても可読性の観点からFORTRANの制御構文を大文字で書き、変数を小文字で記述することが多いようです。
PROGRAM test !プログラム開始文
IMPLICIT NONE !暗黙の型宣言の無効化
INTEGER a,b !変数を宣言
a = 5 !以下実行分の例
b = 7
WRITE(*,*)a+b
END !プログラム終了文
!OUTPUT 12
##文字数制限
FORTRAN77は一行に書き込みできる文字数が72桁分と指定されておりそれをはみ出すと、それ以降の文字は無視されてしまう。そのため指定の文字数を超える場合は改行を行わなければならない。また行の1桁目から6桁目は後述するが、文番号など、別の用途に用いられるため使用できない。したがって、一行に書くことのできる文字数は7桁~72桁目の66文字だけです。
##改行記号
長い数式とかを記述しているとよく文字数の限界に到達してしまいますが、以下のように行の6桁目に$
または&
を置くことで改行し、続けてプログラムを記述することができます。
改行時には1行目の文字数を制限いっぱいまで埋める必要はありません。
!文字型変数の1次元配列MONに月名を初期値として代入する例
CHARACTER MON(12)*3
DATA MON / 'Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun',
$ 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec' /
##コメント行
コメント行はコンパイル時に無視される行で、*
や!
を用いて行のコメントアウトを行います。
*
を用いてコメントアウトするときは*
を行頭に置かなけれなりません。
!
を用いてコメントアウトするときは!
を行のどこに置いてもよく、!
から行末までをコメントアウトします。
!利用例
* コメント
! コメント
a + b !ここから行末までコメント
#FORTRAN77の変数
FORTRANはpythonとかと違い、変数の型推論をやってくれないので事前に型を定めて変数を宣言する必要があります。
ただ、その前にやっておいたほうがよいことが、暗黙の型宣言の無効化です。
##暗黙の型宣言の無効化
暗黙の型宣言を無効化すると、宣言していない変数が実行文中に使われているとコンパイル時にエラーになります。
タイプミスなどのヒューマンエラーをプログラム実行前に除去できるので、利用が推奨されています。
次にそれぞれの型の変数宣言の例を紹介していきます。
##整数型(integer)
整数は4byteで表されるので、$-2^{31} \sim 2^{31}-1$ の整数値をとることができます。
!宣言例
INTEGER i
!複数同時に
INTEGER i,j,k
##実数型(real)
実数は4byteで表される単精度(デフォルト)と8byteで表される倍精度をとります。
!単精度
REAL a
!倍精度
REAL*8 b
###実数の表記法
実数値を記述するときはE,Dを用いた指数表記を使うことが多いです。
!単精度実数ではEを使う
a=1e0 !a = 1.0
a=1E5 !a = 1.0 X 10^5
!倍精度実数ではDを使う
b=0.1D-1 !b = 0.10 X 10^-1
b=-5.0D10 !b = -5.0 X 10^10
##文字型(character)
文字型を宣言するときはその変数が所持できる文字数も同時に記述する必要があります。
CHARACTER char*10 !このときcharは10文字だけ文字を格納することができる
##論理型(logical)
LOGICAL flag
!論理型がとる値は.TRUE.と.FALSE.の2つだけ
DATA flag / .TRUE. /
IF ( flag )THEN
flag = .FALSE.
ENDIF
##DATA文による変数への初期値の代入
変数を宣言した後に以下のようにDATA文を使用することでその変数に初期値を代入することができます。初期値の代入はプログラムの実行に入る前に1度だけ行われます。
REAL*8 x
INTEGER count
DATA x / 0.d0 /
DATA count / 0 /
##PARAMETER文による定数の設定
これまで扱ってきたものは変数であり、プログラムの実行文中でその値を変更することができました。ここでは変数を宣言した後にPARAMETER文を用いて定数を定めます。PARAMETER文で定められた定数は実行文中で変更することはできません。
REAL re
REAL*8 pi
PARAMETER ( re = 6400e3) !()は必要
PARAMETER ( pi = atan(1.D0)*4.D0 ) !宣言時に関数を使ってもOK
ここまでで変数と定数の宣言を見てきました。
次はいよいよFORTRAN77の制御構文に入ります。
#IF文による条件分岐
条件式が真のときそれに対応する実行文を実行します。
分岐はいくつに分けてもよく、またIF文の中にIF文を記述する多重構造になっても構いません。(ただしIF文がクロスすることは不可能)
IF ( 条件式1 ) THEN
実行文1
ELSE IF ( 条件式2 ) THEN
実行文2
ELSE THEN
実行文3
ENDIF
##条件式に用いられる比較演算子
条件式 | 文字表記 | 真を返す条件 |
---|---|---|
a > b | .GT. | aはbより大きい |
a >= b | .GE. | aはb以上 |
a < b | .LT. | aはbより小さい |
a <= b | .LE. | aはb以下 |
a == b | .EQ. | aとbは等しい |
a /= b | .NE. | aとbは等しくない |
##論理演算子
複数の条件式を同時に判定するときには論理演算子を用います。
記号 | 真を返す条件 |
---|---|
( 条件式A ) .AND. ( 条件式B ) | 条件式Aが真かつ条件式Bが真 |
( 条件式A ) .OR. ( 条件式B ) | 条件式Aが真または条件式Bが真 |
#DOループによる繰り返し
##基本的な使い方
INTEGER i !カウンタ変数
DO i=<開始値>,<限界値>,<増分値> !増分値は負でもよい
<処理>
ENDDO
<処理2>
ここでは変数iをDOループのカウンタ変数として使用しています。カウンタ変数は整数でないとダメです。
iにはループの初回に<開始値>が代入されます。ループの中の<処理>が終わるとiの値は<増分値>だけ加算され、加算されたiの値が<限界値>以下であるとき繰り返し処理を行い、iが<限界値>を上回ったとき繰り返し処理を行わずにDO文の下の<処理2>に移ります。
<増分値>は省略することができ、その場合は増分値は1として扱われます。
DOループもif文と同様に多重にすることができますがループがクロスすることは許されません。
##文番号を用いるパターン
文番号を用いるDOループは今後廃止予定みたいですが、それはFORTRAN77には関係ない話で、私が使用している数値モデルのソースにはがっつり使用されているのでその使用例も書いておきます。
INTEGER i
DO <文番号> i=<開始値>,<限界値>,<増分値>
<文番号> CONTINUE
###文番号
文番号は行の先頭に5桁以下の整数を定めます。一つのプログラム中に同じ文番号を定めることはできません。
ループの終点や変数を出力するときのformatを指定するときに文番号は使われます。文番号の決め方にルールはありませんが、プログラムを書くときはダブらないように自分の中でルールを定めておくとよいでしょう。
###CONTINUE文
CONTINUE文は'何も処理を行わない'という実行文です。ENDDO
の代わりに用いられます。
以上をふまえて基本のループと文番号を用いたループで九九を画面に表示するプログラムを書いておきます。
!基本のループ
PROGRAM MAIN
IMPLICIT NONE
INTEGER i,j
DO i=1,9
DO j=1,9
WRITE(*,*)i ,'X',j,'=',i*j
ENDDO
ENDDO
END
!文番号を用いたループ
PROGRAM MAIN
IMPLICIT NONE
INTEGER i,j
DO 10 i=1,9
DO 10 j=1,9
WRITE(*,*)i ,'X', j ,'=',i*j
10 CONTINUE !文番号を用いる場合ループの終点を共有することができる。
END
#次回の予定
次回はサブルーチンの使い方やファイル入出力、プリプロセッサによる条件付きコンパイル、NAMELISTによる変数の代入などをまとめていきたいと思います。
#参考文献
富田博之・斎藤泰洋 共著「Fortran 90/95プログラミング」(2011年 改訂新版)
(この書籍はFortran90/95を対象としているがFORTRAN77式の文法も紹介されており、大変助けられた。)