PC パソコン

Fortran 77・90/95・Modern Fortranの違い|昔と今のコード比較

Fortran 77・90/95・Modern Fortranの違い|昔と今のコード比較

Fortranは非常に長い歴史を持つプログラミング言語です。
そのため、「Fortran」と一言でいっても、
FORTRAN 77、Fortran 90、Fortran 95、
さらにFortran 2003、2008、2018、2023など、
複数の世代があります。

昔Fortranを学んだ人が現在のコードを見ると、
「同じFortranなのにかなり書き方が違う」と感じることがあります。
一方で、基本的な考え方や多くの構文は現在まで受け継がれています。

この記事では、
Fortran 77
Fortran 90/95
Modern Fortranの違いを、
同じ処理を実際のコードで並べながら比較します。

コード内には「!」による注釈も入れ、
どこが昔の書き方で、どこが現在の書き方なのかを
初学者にも分かりやすく説明します。

最初に押さえておきたいFortranの世代

規格 主な特徴
FORTRAN 77 固定形式、行番号、古いDO文などが代表的
Fortran 90 自由形式、配列演算、MODULEなどを導入
Fortran 95 Fortran 90を整理・拡張
Fortran 2003 オブジェクト指向、Cとの相互運用などを強化
Fortran 2008 並列処理関連などを拡張
Fortran 2018 並列・相互運用などをさらに整理・拡張
Fortran 2023 現在の新しい規格世代

この記事では、
Fortran 2003以降の世代をまとめて
Modern Fortranと呼んで説明します。

ただし、「Modern Fortran」という名称は特定の1つの規格名ではなく、
一般にFortran 90以降、特に2003以降の現代的な書き方を指す言葉として使われます。

最大の違い|固定形式と自由形式

FORTRAN 77では、
固定形式(fixed form)という書き方が一般的でした。

固定形式では、
コードを書く桁位置に意味があります。
これはパンチカード時代の設計を引き継いだものです。

      PROGRAM HELLO
      PRINT *, 'HELLO'
      END

左側に空白が並んでいるのは単なる見た目ではありません。
FORTRAN 77では、列位置が重要でした。

一方、Fortran 90以降では
自由形式(free form)が利用できるようになりました。

program hello
    implicit none

    print *, "Hello"

end program hello

現在のFortranでは、
一般的なプログラミング言語と同じように
インデントを自由に付けて読みやすく書けます。

ソースファイルの拡張子にも違いがある

一般的に、古い固定形式のFortranコードでは
.f.forが使われることがあります。

自由形式のFortranでは
.f90が広く使われています。

意味
sample.f 固定形式として扱われることが多い
sample.for 古いFortranコードで見かけることがある
sample.f90 自由形式のFortranで広く使われる

拡張子の数字は、
必ずしも「その規格しか書けない」という意味ではありません。
現在でもModern Fortranの自由形式コードに
.f90を使用するのが一般的です。

Hello Worldを比較する

FORTRAN 77風

      PROGRAM HELLO
C     Cで始まる行は古い形式のコメントです。
      PRINT *, 'HELLO, FORTRAN'
      END

Fortran 90/95風

program hello
    implicit none

    ! Fortran 90以降では ! でコメントを書けます。
    print *, "Hello, Fortran"

end program hello

Modern Fortran

program hello
    implicit none

    print *, "Hello, Fortran!"

end program hello

Hello World程度では、
Fortran 90/95とModern Fortranの見た目はほとんど変わりません。

大きく違うのは、
FORTRAN 77の固定形式から
Fortran 90以降の自由形式へ移った点です。

コメントの書き方を比較する

FORTRAN 77

C     THIS IS A COMMENT
      X = 10.0

固定形式では、
1列目にCや*などを書くコメント形式が使われていました。

Fortran 90以降

! この行はコメントです。

x = 10.0    ! 行の途中にもコメントを書けます。

現在は!を使う書き方が分かりやすく、
一般的です。

DO文の違い

繰り返し処理は、
昔と今の違いが特に分かりやすい部分です。

FORTRAN 77

      INTEGER I

C     Iを1から5まで変化させます。
      DO 100 I = 1, 5
         PRINT *, I

C     100番の文までがDOループです。
  100 CONTINUE

      END

100は行番号(文番号)です。
DO文では「100番の文まで繰り返す」という書き方が使われました。

Fortran 90/95

program do_example
    implicit none

    integer :: i

    do i = 1, 5
        print *, i
    end do

end program do_example

Modern Fortran

program do_example
    implicit none

    integer :: i

    do i = 1, 5
        print *, i
    end do

end program do_example

現在ではend do
繰り返し範囲を明確に書けます。

Fortran 90/95を学んだ人であれば、
この書き方は現在でもほぼそのまま通用します。

IF文を比較する

古い算術IF

非常に古いFortranでは、
値が負・0・正のどれかによって
3つの行番号へ分岐する算術IFが使われることがありました。

      IF (X) 10, 20, 30

   10 PRINT *, 'NEGATIVE'
      GO TO 40

   20 PRINT *, 'ZERO'
      GO TO 40

   30 PRINT *, 'POSITIVE'

   40 CONTINUE

現在のコードとしてはかなり読みづらく、
新しく書く場合に使う必要はありません。

Fortran 90/95以降

if (x < 0.0) then

    print *, "negative"

else if (x == 0.0) then

    print *, "zero"

else

    print *, "positive"

end if

現在では、
こちらの構造化されたIF文を使う方が
はるかに分かりやすくなります。

変数宣言を比較する

FORTRAN 77風

      INTEGER I
      REAL X
      REAL Y

Fortran 90/95以降

integer :: i
real :: x, y

::を使った宣言は、
Fortran 90以降の現代的な書き方です。

implicit noneの重要性

古いFortranでは、
変数名の最初の文字によって型を自動的に決める
暗黙の型付けが使われることがありました。

例えば、I~Nで始まる変数名は整数、
それ以外は実数として扱うという規則です。

      X = 10.0
      I = 5

宣言を書かなくても動く場合があるため、
入力ミスが別の変数として処理される危険があります。

現在は、次のようにimplicit noneを書くのが基本です。

program example
    implicit none

    real :: x
    integer :: i

end program example

これにより、
宣言していない変数を誤って使った場合に
コンパイラが検出しやすくなります。

配列の扱いを比較する

Fortran 90で大きく進化した部分の一つが
配列処理です。

FORTRAN 77風

      REAL A(3)
      REAL B(3)
      REAL C(3)
      INTEGER I

      A(1) = 1.0
      A(2) = 2.0
      A(3) = 3.0

      B(1) = 4.0
      B(2) = 5.0
      B(3) = 6.0

C     各要素をDO文で足します。
      DO 100 I = 1, 3
         C(I) = A(I) + B(I)
  100 CONTINUE

Fortran 90/95

program array_example
    implicit none

    real :: a(3)
    real :: b(3)
    real :: c(3)

    a = (/ 1.0, 2.0, 3.0 /)
    b = (/ 4.0, 5.0, 6.0 /)

    ! 配列全体を一度に加算できます。
    c = a + b

end program array_example

Modern Fortran

program array_example
    implicit none

    real :: a(3)
    real :: b(3)
    real :: c(3)

    ! 現在は [ ] を使った配列コンストラクタも利用できます。
    a = [1.0, 2.0, 3.0]
    b = [4.0, 5.0, 6.0]

    c = a + b

    print *, c

end program array_example

Fortran 90以降では、
配列全体を1つの式として計算できるようになりました。
これは科学技術計算における大きな利点です。

動的配列の違い

FORTRAN 77では、
配列サイズをあらかじめ固定しておく使い方が一般的でした。

      REAL DATA(1000)

Fortran 90以降では、
allocatableを使って
実行時に必要なサイズを確保できます。

program allocatable_example
    implicit none

    integer :: n
    real, allocatable :: data(:)

    print *, "要素数を入力してください。"
    read *, n

    ! 実行時にn個の配列を確保します。
    allocate(data(n))

    ! ここでdataを使用します。

    ! 使用後に領域を解放します。
    deallocate(data)

end program allocatable_example

必要なデータ数が実行時まで分からない場合に便利です。

関数の書き方を比較する

FORTRAN 77風

      REAL FUNCTION SQUARE(X)
      REAL X

C     関数名そのものへ値を代入して返します。
      SQUARE = X * X

      RETURN
      END

Fortran 90/95以降

function square(x) result(answer)
    implicit none

    real, intent(in) :: x
    real :: answer

    answer = x * x

end function square

Modern Fortranでは、
resultintentを使うことで、
入力と出力の意味を明確に書けます。

サブルーチンを比較する

FORTRAN 77風

      SUBROUTINE CALC(A, B, C)
      REAL A, B, C

      C = A + B

      RETURN
      END

Modern Fortran

subroutine calc(a, b, c)
    implicit none

    ! aとbは入力専用です。
    real, intent(in) :: a
    real, intent(in) :: b

    ! cは出力用です。
    real, intent(out) :: c

    c = a + b

end subroutine calc

intent(in)intent(out)によって、
引数の役割がコードを見ただけで分かります。

COMMONとMODULEの違い

古いFortranでは、
複数のプログラム単位で変数を共有するために
COMMONが使われることがありました。

FORTRAN 77風

      REAL A, B
      COMMON /DATA/ A, B

COMMONは古いコードで頻繁に見かけますが、
変数の管理が分かりにくくなることがあります。

Fortran 90以降では、
MODULEを使って
変数や関数、サブルーチンなどを整理できます。

Fortran 90以降

module constants
    implicit none

    real, parameter :: pi = 3.14159265

end module constants

利用する側ではuseを書きます。

program circle
    use constants
    implicit none

    real :: radius
    real :: area

    radius = 5.0
    area = pi * radius ** 2

    print *, area

end program circle

MODULEはModern Fortranで非常に重要な仕組みです。

GOTOは現在でも使える?

Fortranにはgotoがあります。
昔のFortranコードでは、
行番号と組み合わせて処理を移動するコードをよく見かけます。

      IF (X .GT. 0.0) GO TO 100

      PRINT *, 'ZERO OR NEGATIVE'
      GO TO 200

  100 PRINT *, 'POSITIVE'

  200 CONTINUE

現在でも一部のgoto構文は利用できますが、
新しいコードでは、
IF、DO、SELECT CASEなどを使って
構造化して書く方が読みやすくなります。

比較演算子の昔と今

古いコードでは、
次のような文字形式の比較演算子をよく見かけます。

古い表記 現在よく使う表記 意味
.EQ. == 等しい
.NE. /= 等しくない
.GT. > より大きい
.LT. < より小さい
.GE. >= 以上
.LE. <= 以下

古い書き方

      IF (X .GT. 10.0) THEN
         PRINT *, 'LARGE'
      END IF

現在の書き方

if (x > 10.0) then
    print *, "large"
end if

古い文字形式の演算子も現在のコンパイラで扱えることがありますが、
新しいコードでは記号形式の方が一般的です。

文字列の扱い

FORTRAN 77風

      CHARACTER*20 NAME
      NAME = 'FORTRAN'

Modern Fortran

character(len=20) :: name

name = "Fortran"

character(len=20)のように書く方が
意味が明確です。

SELECT CASEを使える

Fortran 90以降では、
複数条件の分岐にselect caseを利用できます。

program select_example
    implicit none

    integer :: number

    number = 2

    select case (number)

    case (1)
        print *, "one"

    case (2)
        print *, "two"

    case default
        print *, "other"

    end select

end program select_example

昔の大量のGOTOを使った分岐より、
処理の構造が分かりやすくなります。

同じ処理を3世代で比較|1から10までの合計

FORTRAN 77

      PROGRAM SUM10

      INTEGER I
      INTEGER TOTAL

      TOTAL = 0

C     1から10まで繰り返します。
      DO 100 I = 1, 10

         TOTAL = TOTAL + I

  100 CONTINUE

      PRINT *, TOTAL

      END

Fortran 90/95

program sum10
    implicit none

    integer :: i
    integer :: total

    total = 0

    do i = 1, 10
        total = total + i
    end do

    print *, total

end program sum10

Modern Fortran

program sum10
    implicit none

    integer :: numbers(10)
    integer :: i
    integer :: total

    ! 配列へ1~10を代入します。
    do i = 1, 10
        numbers(i) = i
    end do

    ! sumを使って配列全体を合計できます。
    total = sum(numbers)

    print *, total

end program sum10

Modern Fortranでは、
DO文を使う方法ももちろん有効ですが、
配列処理や組み込み関数を使って
より簡潔に書ける場面があります。

同じ処理を比較|配列の平均値

FORTRAN 77風

      PROGRAM AVERAGE

      REAL DATA(5)
      REAL TOTAL
      REAL AVG
      INTEGER I

      DATA(1) = 10.0
      DATA(2) = 20.0
      DATA(3) = 30.0
      DATA(4) = 40.0
      DATA(5) = 50.0

      TOTAL = 0.0

      DO 100 I = 1, 5
         TOTAL = TOTAL + DATA(I)
  100 CONTINUE

      AVG = TOTAL / 5.0

      PRINT *, AVG

      END

Modern Fortran

program average
    implicit none

    real :: data(5)
    real :: average_value

    data = [10.0, 20.0, 30.0, 40.0, 50.0]

    ! sumで合計し、sizeで要素数を取得します。
    average_value = sum(data) / real(size(data))

    print *, average_value

end program average

この比較を見ると、
配列演算や組み込み関数によって
現代のFortranコードがかなり簡潔になっていることが分かります。

昔のFortranコードは現在でも動く?

多くの場合、
現在のFortranコンパイラは古いコードとの互換性をかなり重視しています。

例えばGNU Fortran(gfortran)は、
FORTRAN 77やFortran 90/95のコードを
現在でも多数コンパイルできます。

Fortran 90/95で書かれた自由形式コードであれば、
現在のgfortranでもかなりそのまま使える場合があります。

一方、非常に古いコードでは、
現在の規格から削除された機能や、
非推奨になった機能が含まれていることがあります。

古いコードで見かける機能

  • 固定形式
  • 文番号付きDO
  • 算術IF
  • assigned GO TO
  • COMMON
  • 古いDATA文
  • 古いFORMAT文
  • 暗黙の型付け

このようなコードは、
そのまま動く場合もあれば、
コンパイラオプションやコード修正が必要になる場合もあります。

gfortranで古いコードを試す

例えば古い固定形式コードが
old.fという名前で保存されている場合、
まずは通常どおりコンパイルしてみます。

gfortran old.f -o old

古い拡張機能が使われている場合は、
gfortranのレガシーモードが役立つことがあります。

gfortran -std=legacy old.f -o old

ただし、
レガシーモードで動くからといって
新しいプログラムでも古い書き方を使う必要はありません。

既存コードを動かす場合は互換機能を利用し、
新しく書くコードではModern Fortranの読みやすい構文を使う、
という考え方が分かりやすいでしょう。

Fortran 90/95を学んだ人はどの程度そのまま使える?

Fortran 90/95を学んだ経験がある場合、
現在のFortranでも基本的な知識の多くはそのまま利用できます。

例えば次のようなものは現在でも重要です。

  • program ~ end program
  • implicit none
  • integer、real、character
  • IF ~ THEN ~ END IF
  • DO ~ END DO
  • 配列
  • function
  • subroutine
  • module
  • allocate / deallocate

つまり、
Fortran 90/95は「完全に古い別言語」ではありません。
現在のModern Fortranへ直接つながる重要な世代です。

新しいコードではどの書き方を使えばよい?

これからFortranを学ぶ場合は、
基本的にModern Fortranの書き方を使うのがおすすめです。

例えば次のような方針です。

  • 自由形式で書く
  • .f90を使用する
  • implicit noneを書く
  • DO ~ END DOを使う
  • 構造化IFを使う
  • 配列演算を利用する
  • COMMONよりMODULEを使う
  • 引数にはintentを付ける
  • 必要に応じてallocatableを使う

昔の書き方を学ぶ意味はある?

新しいプログラムを書くためだけなら、
FORTRAN 77の古い構文を覚える必要はあまりありません。

しかし、研究機関、大学、企業などでは、
何十年も改良されてきたFortranコードが残っていることがあります。

そのため、
古いFortranコードを読む必要がある人にとっては、
固定形式、行番号、COMMON、文番号付きDOなどを
知っておくと役立ちます。

特に、
「昔のコードを現在の環境へ移植する」
「古い科学計算プログラムを理解する」
という場面では重要です。

Fortranの変化をまとめる

項目 FORTRAN 77 Fortran 90/95 Modern Fortran
ソース形式 固定形式が中心 自由形式を導入 自由形式が一般的
DO 文番号を利用することが多い END DO END DO
配列演算 DOループ中心 配列全体の演算が可能 さらに活用
動的配列 限定的 ALLOCATABLE 広く利用
共有データ COMMON MODULE MODULE
引数の役割 明示しにくい INTENT INTENT
コメント Cなど ! !
コードの読みやすさ 古い形式では低くなりやすい 大幅に改善 さらに構造化可能

まとめ

FORTRAN 77と現在のFortranを比較すると、
見た目やコードの構造は大きく変わっています。

特に、
固定形式から自由形式への移行、
文番号付きDOからEND DOへの変更、
配列演算、MODULE、ALLOCATABLEなどの導入によって、
コードはかなり読みやすくなりました。

一方、Fortran 90/95はModern Fortranとの共通点が多く、
当時学んだ知識の多くは現在でも利用できます。

また、現在のgfortranは古いFortranコードも広く扱えるため、
過去の科学技術計算プログラムを現在のパソコンで動かせる場合があります。

これから新しくFortranを書く場合はModern Fortranの書き方を使い、
古いコードを読む必要があるときに
FORTRAN 77特有の構文を理解する、
という学び方が実用的でしょう。