next up previous
Next: 2 FORTRAN プログラムのコンパイルと実行 Up: 4 計算機言語入門 Previous: 4 計算機言語入門

Subsections


1 FORTRAN 入門

計算機の言語には色々なものがある。それぞれ特徴を持っており、分野や用途によっ て使い分けられている。科学計算においては、FORTRAN の重要度が高い。C や C++ も 良く使われる。他に、数式処理のための言語として、REDUCE や LISP や Mathematica も重 宝である。また、 awk, perl, ruby といったスクリプト言語と言われるものもある。 どう分類するか難しいが Java も様々なところで使われている 多くの計算機環境では、こういった言語を組み合わせて使用する事が出来るので、用 途や目的に応じて、multilingual な特徴を生かした使い方をするのが良いで あろう。

実際に天文学の研究をするという観点からは、多くの場合に様々な言語を使う 必要に迫られる。というのは、観測的研究、理論的研究のどちらにしても、 (本当に「紙と鉛筆」だけでできる理論的研究の一部を別にすれば)計算機を使っ てデータ解析やシミュレーションをすることが必須であり、そのためのプログ ラムを作る必要がある。ところが、こういったプログラムは大規模・複雑なも のになってきており、一人でゼロから書けるものではなかなかない。何人もが 共同で作ったり、また、過去に別の人が作ったものを変更・改良して使うこと が普通である。このために、過去の資産が Fortran であれば Fortran が使え ないといけないし、C であればそれでなんとかする必要がでてくる。

この講義では Fortran を扱い、計算天文学 II では C++ を扱うことにする。 2 種類の非常に違う言語を短期間に扱うのは混乱を招く面もあることは否定し ないが、逆に言語1つだけしか知らないと、2番目を学ぶのは非常にハードルが 高いからである。2つの言語を一応理解していると、その間には共通点と相違 点があることが分かり、さらに他の言語を理解する必要ができた時にも類推が 効くようになる。

FORTRAN は、1950年代に開発された言語で、計算機言語としては、歴史が古い。進歩 の速い計算機に関しては、歴史が古いという事は、多くの場合、陳腐で劣る事を意味 する事が多い。事実、50年代或いはそれ以後開発された言語で、今日では使用されな くなった言語は非常に多い。そういった環境の中にあっても、FORTRAN は、色々な意 味で、優れた点を多く持った言語なので、様々な改良を加えられながら、今日まで、 科学計算用の標準的言語の一つとして、使われ続けている。その特徴としては、

等が挙げられよう。

なお、Fortran の言語仕様には、 Fortran 66, 77, 90 とほぼ 10年毎に大き な改訂が加えられてきた。この講義では、基本的には 77 に準拠するが、 90 での拡張をある程度取り入れた形でプログラムを書く。現在広く使われている のがその形であり、また計算機室のシステムで利用可能なのもそれだからである。

計算機の演算能力を最大限に発揮するには、計算機が直接理解できる機械語(アセン ブラ)でプログラムを書けば良いのだが、このためには、プログラムを書く人間の側 に多大の努力を要し、効率悪く、とても一般の人向きではない。そこで、FORTRAN 等、 人間が理解しやすい言語でプログラムを書き、それを機械語に翻訳させる作業(コン パイルという)を計算機自身にさせる訳だが、FORTRAN には、高速にしかも最適化され た機械語に翻訳する技法が進んだ形で取り入れられている。これらの理由から、 FORTRANは長い間多く利用され、それが更に、ライブラリを完備させる等、良い方向に フィードバックされて、より便利な道具として使われる理由となっている。

FORTRAN を使って計算をしたい時には、FORTRAN の言語で書かれた一つのファイルを 先ず作らなければならない。こういったファイルをプログラムと呼ぶ。例として、球 の半径が与えられた時に、球の表面積と体積を求める計算を考えよう。そのためのプ ログラムの例は、第[*]章で、エディタを使ってのファイル作成練習で書い た、sphere.fである。念のため、下に掲げておこう [*]

      Program sphere
      Implicit NONE
c constant:
      Real PI
      Parameter (PI=3.141593)
c local variable:
      Real radius
      Real area, volume
c begin:
      radius = 10.0
      area   = 4. * PI * radius**2
      volume = area * radius /3.
      Write(*,*) 'radius:',radius
      Write(*,*) ' surface area =',area,' volume =',volume
c end:
      Stop
      End

1 FORTRAN の約束事

FORTRAN は、カードでプログラムを入力していた時代 (と言っても、何の事かわからない世代の時代になってしまった。 要するに、太古の時代からの意味)から使われていたせいで、プロ グラムを書く上で、様々な制約、約束事がある。

2 式と代入

左辺=右辺 で右辺の値を左辺の変数の値とする。左辺は変数でなければならない。 右辺は数値もしくは数式だが、数式の場合はその段階で数値計算可能である必要がある。

例.

      a = 1.0
      b = a + 1.0

3 四則演算

右辺で行う四則演算は表4.1の様に記す。


Table 4.1: FORTRAN での四則演算
演算 FORTRAN
加算 $+$ x + y
減算 $-$ x - y
掛算 $*$ x * y
割算 $/$ x/y
冪乗 $**$ x**y
括弧 $($ $)$ (2.*(x + y))/(3.*(a + b))

4 変数と型

FORTRAN が扱う変数には、整数、実数、複素数、 論理型、文字列がある。サンプルプログラムの中で、local variables の次の 行で、Real radius とあるのは、radius という変数が実数型である事を 宣言している。整数、実数、複素数を混合して演算しないようにプログラムを書くことを心掛けたい。 混合演算をすると、右辺の代入結果は左辺の変数の型になる。 表4.2に、変数と型に関する制限事項をまとめる。

5 宣言文

変数の型を宣言する例を見た。他にもこういった宣言文がある。 先の例では、
      Implicit NONE
      Parameter (PI=3.141593)
がそうだ。最初の例は、そのプログラムで使用する変数は全て型宣言をしてから 使う事を宣言している。FORTRAN では、最初の文字によって、計算機が型を暗黙 のうちに解釈するという、便利なような恐ろしいような約束事がある。一見便利 なようなルールだが、プログラムを書き直したり、長いプログラムを書く時等、 使う変数をきちんと把握している方が、結局は便利である事の方が多い。 Implicit NONEをプログラムの頭で宣言しておくと、 型宣言していない変数をプログラム中で引用していたら、計算機が警告してくれる。


Table 4.2: FORTRANで扱われる変数の型
FORTRAN 大きさ
整数型 Integer $-32768 \sim 32767$
  Integer*4 $-2147483648 \sim 2147487647$
実数型 Real $\pm 0.29\times 10^{-38} \sim \pm 1.7\times 10^{38}$ (有効数字7桁)
  Real*8 $\pm 0.29\times 10^{-38} \sim \pm 1.7\times 10^{38}$ (有効数字15桁)
複素数型 Complex (有効数字7桁)
  Complex*16 (有効数字15桁)
論理型 Logical .true.(真)或いは .false.(偽)
Logical*2  
文字型 Character*サイズ サイズ分の長さの文字列

二番目の例のParameter文は、変数PIの値を指定している。式として 書いても同じ事だが、物理定数等このParameter文を用いて宣言すると、 値を直す時等、場所が決まっているから、便利である。

DIMENSIONの宣言は、良く使うであろう。$y_i$ $(i=1,...,10)$ 等を変数として、 使いたい時がある。この様な時、

      DIMENSION y(10)
の様に宣言すると、y(1), ... , y(10) が使えるようになる。引数が 二次元ならば、
      DIMENSION y(i,j)
の様にすれば良い。ijは、それより前の Parameter文でサイズを宣言して おけば良い。

6 WRITE 文

先のプログラムで、
      Write(*,*) 'radius:',radius
      Write(*,*) ' surface area =',area,' volume =',volume
が、WRITE文である。'radius:'radius:と表示させる事を意味し、 カンマに続くradiusは、変数radiusの値を表示させる事を意味している。

7 IF 文

変数の値などの条件によって、次に行うべき演算が違う事がある。 FORTRAN では、次の様にして場合分けを行う。
      if (code.eq.1) then
         ...
      else
         ...
      end if
或いは次の様な更に細かい条件分岐も出来る。
      if (code.gt.1) then
         ...
      else if (code.eq.1) then
         ...
      else
         ...
      end if

8 DO ループ

例えば

\begin{displaymath}y = \sum_{i=1}^{10} a_i\end{displaymath}

を計算するために、DOループと呼ばれる繰り返し演算がある。
      y = 0.0
      Do i=1,10
        y = y + a(i)
      End do
iが10以下である限り繰り返すといった場合には、次の様なDo whileが便 利だ。
      i = 1
      Do while (i.le.10)
        y = y + a(i)
        i = i + 1
      End do

9 条件判断

If文やWhile文の条件判断では、大小符号や真偽等を条件として使うが、 それらは次のように表される。


Table 4.3: FORTRANで扱う大小符号や等号
関係式 FORTRAN
$a = b$ a.eq.b
$a \neq b$ a.ne.b
$a < b$ a.lt.b
$a \leq b$ a.le.b
$a > b$ a.gt.b
$a \geq b$ a.ge.b
$a \wedge b$ a.and.b
$a \vee b$ a.or.b
$\neg a$ .not.a

10 サブルーチン

先に掲げた球の表面積と体積を求める計算で、半径を1から2刻みで10まで変えて計算 する事を考えよう。同じ作業の繰り返しだから、その部分だけを別のパーツとしてプ ログラムを構築できたら、プログラムは短く、かつ見易いものとなるであろう。 サブルーチンはこの様な目的に、使われるプログラムのパーツである [*]

      Program sphere2
      Implicit NONE
c constant:
      Real RADIUS_INITIAL,MAX_RADIUS,DELTA_R
      Parameter(RADIUS_INITIAL=1.0,MAX_RADIUS=10.0)
      Parameter(DELTA_R=2.0)
c local variable:
      Real radius
      Real area, volume
c begin:
      radius = RADIUS_INITIAL
      Do while (radius .le. MAX_RADIUS)
         Call calculation(radius, area, volume)
         Write(*,*) 'radius:', radius
         Write(*,*) ' area =',area,' volume =',volume
         Write(*,*)
         radius = radius + DELTA_R
      End do
      Stop
      End

      Subroutine calculation(radius, area, volume)
      Implicit NONE
c input:
      Real radius
c output:
      Real area, volume
c constant:    
      Real PI
      Parameter (PI=3.141593)
c begin:
      area   = 4. * PI * radius**2
      volume = area * radius /3.
      Return
      End
メインプログラムでは、半径を与えるだけで、計算はサブルーチンcalculation で行っている。そしてメインプログラムとサブルーチンとの間のやり取りは、メイン プログラム中のcall文で行う。その際、引数(radius,area,volume)は、 radius がメインプログラムから与えられ、areavolumeは、サブ ルーチンから計算の結果として、メインプログラムに返される。 それぞれの引数の型は、メインプログラムとサブルーチンの間で必ず一致させなけれ ばならない。但し、引数の名前は両者の間で異なっていても構わない。 この例に見るように、引数はメインプログラムからサブルーチンにも渡せるし、 逆にサブルーチンからメインプログラムにも渡せる。どちらからどちらに渡されてい るかは、一見して明らかな訳ではないので、上のサブルーチンcalculationの 例のように、コメントで注釈を附けておくと、便利である。 また、サブルーチンから、別のサブルーチンを呼ぶことも出来る。 サブルーチンはReturnEndで終わるのが約束である。

11 READ 文

先に掲げた球の表面積と体積を求めるプログラムでは、球の半径は、プログラムの中で 与えた。任意の半径を与えられるようにならないだろうか。下に掲げるプログラムは、 端末から、半径を与える様に、sphere2.fを直したものである [*]。 (サブルーチンcalculationは再掲していない。)

      Program sphere3
      Implicit NONE
c constant:
      Real RADIUS_INITIAL,MAX_RADIUS,DELTA_R
c local variable:
      Real radius
      Real area, volume
c begin:
      Write(*,*) 'Input RADIUS_INITIAL:'
      Read(*,*) RADIUS_INITIAL
      Write(*,*) 'Input MAX_RADIUS:'
      Read(*,*) MAX_RADIUS
      Write(*,*) 'Input DELTA_R:'
      Read(*,*) DELTA_R

      radius = RADIUS_INITIAL
      Do while (radius .le. MAX_RADIUS)
         Call calculation(radius, area, volume)
         Write(*,*) 'radius:', radius
         Write(*,*) ' area =',area,' volume =',volume
         Write(*,*)
         radius = radius + DELTA_R
      End do
      Stop
      End

Read(*,*)が、端末から変数を読み込ませるときに用いる文である。

12 ファイルへの入出力

上の例で、Read文やWrite文で、端末に入出力するのではなく、 ファイルに入出力するには、次の様にすれば良い [*]

      Program sphere4
      Implicit NONE
c constant:
      Real RADIUS_INITIAL,MAX_RADIUS,DELTA_R
c local variable:
      Real radius
      Real area, volume
c file open:
      Open(Unit=2,File='Input.dat',Status='OLD')
      Open(Unit=3,File='Output.dat',Status='NEW')
c begin:
      Read(2,*) RADIUS_INITIAL,MAX_RADIUS,DELTA_R
      radius = RADIUS_INITIAL
      Do while (radius .le. MAX_RADIUS)
         Call calculation(radius, area, volume)
         Write(3,*) 'radius:', radius
         Write(3,*) ' area =',area,' volume =',volume
         Write(3,*)
         radius = radius + DELTA_R
      End do
      Stop
      End

(*,*)のところが(2,*)となったため、入力は2番の論理装置から行なわれ る。その2番の論理装置がInput.datという名前の既製のファイルである事を 最初のOpen文が記述している。 Write文が、(3,*)であるから、出力は 3番の論理装置に対してなされる。 二つ目のOpen文は、同様に3番の論理装置がInput.datという名前の の新規のファイルである事を記述している。

13 入力回数が予め決まっていない場合

入力データの数が予めわかっている場合は、先の方法や、それをDOループで データの読み込み回数分だけ繰り返せば良いが、入力データの数が予めわかっていな い場合はどうすれば良いであろうか。FORTRANのREAD分は、この様な場合に備えて、 論理装置番号、読み込み形式を表す*のほかに、もう一つ割り込み文番号を指定 できるようになっている。次のプログラム [*]で、Read文が(2,*)ではなく、(2,*,end=900)となっている事に 注意しよう。これは、N回までDOループが回ろうとしているうちに、 読み込みデータがなくなったら、900番の文番号に飛ぶ事を意味している。 900番の文では、その時点での変数iを書き出すように命令しているから、 これにより、幾つデータを読んだかが判る。この様な場合、DO文は、途中で割 り込みが入ることになり、完結しないことに注意しておこう。
      Program sphere5
      Implicit NONE
c constant
      Integer N
      Parameter(N=2000)
c local variable:
      Real radius
      Real area, volume
      integer i
c file open:
      Open(Unit=2,File='Input.dat',Status='OLD')
      Open(Unit=3,File='Output.dat',Status='NEW')
c begin:
      Do i=1,N
         Read(2,*,end=900) radius
         Call calculation(radius, area, volume)
         Write(3,*) 'radius:',radius,' area =',area,' volume =',volume
      End do
  900 Write(*,*) 'number of data=', i-1

      Stop
      End
このプログラムで、N以上読み込みデータがあると、number of data として正しくない答えNを表示する。

14 組み込み関数

計算の中で、三角関数などの関数を使いたい場合も多い。FORTRAN には 様々な関数が標準で用意されており、それらを利用する事が出来る。 例えば、プログラムの中でy=cos(x)とあれば、変数yには、変数x の余弦が代入される。良く使われる関数を表4.4に掲げる。


Table 4.4: FORTRAN の組込み関数
FORTRAN 意味 FORTRAN 意味
sqrt(x) $\sqrt{x}$ exp(x) $\exp (x)$
log(x) $\ln x$ log10(x) $\log x$
sin(x) $\sin x$ asin(x) $\arcsin x$
cos(x) $\cos x$ acos(x) $\arccos x$
tan(x) $\tan x$ atan(x) $\arctan x$
sinh(x) ${\rm sinh} x$ cosh(x) ${\rm cosh} x$
tanh(x) ${\rm tanh} x$ abs(x) $x$の絶対値
int(x) $x$の整数部 float(n) 整数$n$を実数に変換
max(x,y,z,...) $x, y, z, ...$の最大値 min(x,y,z,...) $x, y, z, ...$の最小値

混合演算をしないように、と書いたが、実数xを整数に型変換するには、 int(x)を使い、整数xを実数に型変換するには、float(x)を 使う。

15 自分で定義して作る外部関数:FUNCTION 文

FORTRANが用意してくれる標準的関数以外に、自分で外部関数を定義して使う事も 出来る。 例えば、球の表面積と体積を半径の関数として、それぞれ関数 S(r)V(r)
      real function S(r)
      implicit NONE
c constant:
      real PI
      parameter (PI=3.141593)
c local variable:
      real r
c begin:
      S=4.*pi*r**2
      return
      end


      real function V(r)
      implicit NONE
c constant:
      real PI                                                    
      parameter (PI=3.141593)
c local variable:
      real r
c begin:
      V=4./3.*pi*r**3
      return
      end
で定義して、メインプログラムからは、
      Program sphere6
      Implicit NONE
c constant:
      Real RADIUS_INITIAL,MAX_RADIUS,DELTA_R
c local variable:
      Real radius
      Real area, volume, S, V
c begin:
      Write(*,*) 'Input RADIUS_INITIAL:'
      Read(*,*) RADIUS_INITIAL
      Write(*,*) 'Input MAX_RADIUS:'
      Read(*,*) MAX_RADIUS
      Write(*,*) 'Input DELTA_R:'
      Read(*,*) DELTA_R

      radius = RADIUS_INITIAL
      Do while (radius .le. MAX_RADIUS)
         Write(*,*) 'radius:', radius
         area  =S(radius)
         volume=V(radius)
         Write(*,*) ' area =',area,' volume =',volume
         Write(*,*)
         radius = radius + DELTA_R
      End do
      Stop
      End
のように、外部関数を使う。FUNCTION 文は、メインプログラムの後ろにつけて、コン パイルするのが良いだろう [*]

16 参考書

FORTRANの文法や利用法等、とてもこのテキストでは書ききれないので、以下に掲げる ような参考書で自習して欲しい。

浦 昭二: FORTRAN入門(3訂版)(培風館)

森口繁一:JIS FORTRAN入門(第3版)上・下 (東大出版会)


next up previous
Next: 2 FORTRAN プログラムのコンパイルと実行 Up: 4 計算機言語入門 Previous: 4 計算機言語入門
Jun Makino
平成15年4月24日