回数の決まったくりかえしの構文

Fortranでは、回数の決まったくりかえしを表現するのに、DO文を使う。

増田の教材の例文は、次のような構文をよく使う。 ここでは、Fortran 77標準に従ってDO文を記述している。

===== BEGIN loop1.f
      PROGRAM doloop
      INTEGER kt, nt
      REAL    t, deltat
*
      READ (*,*) nt, deltat
      DO 100 kt = 1, nt
        t = kt * deltat
        write (*,*) kt, t
  100 CONTINUE
      END
===== END loop1.f

実は、g77やDEC Fortranコンパイラでは、 Fortranの新しい標準(90標準)で認められたDO...END DO構文を使うことができる。 文番号(loop1.fの100)を使わなくてよいので、このほうがすぐれているのだが、 まだすべてのコンパイラで使えるとは限らない。 1996年度以後、わたしの例文では、文番号のない方式を原則にするつもりだが、 両方の方式が混じるかもしれない。

===== BEGIN loop2.f
      PROGRAM doloop
      INTEGER kt, nt
      REAL    t, deltat
*
      READ (*,*) nt, deltat
      DO kt = 1, nt
        t = kt * deltat
        write (*,*) kt, t
      END DO
      END
===== END loop2.f

上の例の kt のような制御変数をもたない繰り返し構文もある。 まず、77標準の範囲で同じ仕事内容を表現すると次のようになる。

===== BEGIN loop3.f
      PROGRAM doloop
      INTEGER kt, nt
      REAL    t, deltat
*
      READ (*,*) nt, deltat
      kt = 1
 9000 IF (kt .GT. nt) GO TO 9900
        t = kt * deltat
        write (*,*) kt, t
        kt = kt+1
      GO TO 9000
 9900 CONTINUE
      END
===== END loop3.f

90標準の構文を使えば、文番号を使わずに表現できる。

===== BEGIN loop3a.f
      PROGRAM doloop
      INTEGER kt, nt
      REAL    t, deltat
*
      READ (*,*) nt, deltat
      kt = 1
      DO WHILE (kt .LE. nt)
        t = kt * deltat
        write (*,*) kt, t
        kt = kt+1
      END DO
      END
===== END loop3a.f

なお、次のように、ループ終了判定を実数型の変数でおこなうのは 避けたほうがよい。誤差が累積するからである。 loop4a.f のループ内のwrite文をやめ、最後にt, ktの値を出力するよう 修正したものをloop5a.fとしてあるので、 nt, deltat に、たとえば 100, 0.01 を与えてためしてみてほしい。 この例文 loop4a.f、loop5a.f では、 ktは結果として計算しているだけで、ループの制御に関与していない。

===== BEGIN loop4a.f
      PROGRAM doloop
      INTEGER kt, nt
      REAL    t, deltat, tfinal
*
      READ (*,*) nt, deltat
      tfinal = nt*deltat
      t  = 0.0
      kt = 0
      DO WHILE (t .LE. tfinal)
        t  = t  + deltat 
        kt = kt + 1
        write (*,*) kt, t
      END DO
      END
===== END loop4a.f

===== BEGIN loop5a.f
      PROGRAM doloop
      INTEGER kt, nt
      REAL    t, deltat, tfinal
*
      READ (*,*) nt, deltat
      tfinal = nt*deltat
      WRITE (*,*) 'final t should be   ', tfinal
      t  = 0.0
      kt = 0
      DO WHILE (t .LE. tfinal)
        t  = t  + deltat 
        kt = kt + 1
*       write (*,*) kt, t
      END DO
      WRITE (*,*) 'final t is actually ', t  
      WRITE (*,*) 'loop count          ', kt 
      END
===== END loop5a.f


1996-04-29; 2003-05-29
増田 耕一

目次へ