先日 NASA が1977年に打ち上げられたボイジャー探査機のメンテナンスのために FORTRAN のエンジニアを募集しているという記事を見た。
http://www.theregister.co.uk/2015/10/31/brush_up_on_your_fortran/
「FORTRAN が書ける人間がいるわけがない」「あれはIT業界のインダス文字だ」「NASA は暗に宇宙人に募集をかけてるのではないか」と思った人も多いと思うが、科学技術計算界隈ではわりと普通に FORTRAN が現役である。そこで本稿では FORTRAN を面白おかしく紹介しようと思う。
FORTRAN は歴史が長いだけあって様々なバージョンがあるが、FORTRAN 77 は アルファベットの小文字が使えない などの仕様があり、気の弱いエンジニアは見るだけで失神するだろう。本稿は全年齢対象という観点から、コードの視覚的な危険性の薄い Fortran 90 について述べる。
コンパイラはおそらく最も普及している gfortran を用いているため、gfortran の仕様なのか Fortran 90 の仕様なのかを区別していないが、まあネタ記事ということでご了承願いたい。
変数宣言は、なくても良いが絶対必要
C 同様のコンパイル言語なので変数宣言が必要かと思いきや、実は宣言しなくても使える。
program main
x = 3.14
n = 3.14
print *, "x = ", x
print *, "n = ", n
end program
Fortran 自体を知らなくても意味は分かるだろう。x
と n
にそれぞれ 3.14
を代入して表示するという他愛ないプログラムだ。だがこれを実行すると
x = 3.14000010
n = 3
おわかりいただけただろうか。Fortran は x,y,z
といった文字は実数、n,m
といった文字は整数というふうに 値ではなく変数名から型推論 をするという機能がある。
この機能はおそらくコンピュータ黎明期には便利だったのだろうが、野蛮過ぎるということで当時のキリスト教会により弾圧された。現代では implicit none
という悪魔祓いのおまじないを入れることが義務付けられている。これは「変数宣言なしで変数使ったらコンパイルエラー出すよ」という意味。
program main
implicit none
x = 3.14
n = 3.14
print *, "x = ", x
print *, "n = ", n
end program
これをコンパイルするとエラーが出る。
test.F90:4:3:
n = 3.14
1
Error: Symbol ‘n’ at (1) has no IMPLICIT type
test.F90:3:3:
x = 3.14
1
Error: Symbol ‘x’ at (1) has no IMPLICIT type
配列番号は ( ) で囲む
配列 p
の5番目の要素にアクセスするには p[5]
ではなく p(5)
と書く。
「エッ、それじゃ関数に引数を渡すときはどう書くの?」と思うだろう。他の言語同様 func(arg)
である。なんて紛らわしいんだ!
ちなみに配列番号は1から始まる。
program main
implicit none
integer p(5)
p(1) = 2
p(2) = 3
p(3) = 5
p(4) = 7
p(5) = 11
print *, p
end program
2 3 5 7 11
配列を print
すれば要素を全部表示してくれる。この点 C よりもだいぶラクと言えるだろう。他にも「配列全体に対する操作」というのが充実していて、たとえば
real x(10)
x = 1.0
とすれば x
の10要素すべてに 1.0 を代入してくれるし
sin(x)
とすれば x の要素すべてに sin()
関数を適用してくれる。また大抵の言語で扱いのめんどい多次元配列も
integer x(10,10)
こうすればあっさり 10x10 の二次元配列になる。
充実の数学機能
もとを正せばコンピュータとは計算機なので、元祖高級言語である Fortran は数学機能がやたら充実している。たとえば複素数型 complex
というマニアックな機能がなんの追加モジュールもなしに使える。以下は複素数 z=1+2i の自乗計算である。
program main
implicit none
complex z
z = (1.0, 2.0)
print *, z**2
end program
( -3.00000000 , 4.00000000 )
また、同じ長さの配列はループなどせずにそのまま足し算することが出来る。いわばベクトルとして扱われている。
program main
implicit none
integer a(3), b(3)
a(1) = 10
a(2) = 20
a(3) = 30
b(1) = 40
b(2) = 50
b(3) = 60
print *, a+b
end program
50 70 90
このように単純な計算が C よりずっとラクに書けて、しかもスクリプト言語よりも桁違いに計算が速いので、いまだに科学計算で使われるのもまあ分からんでもないだろう。