このページでは、Fortranを使ったプログラミングの基礎を学びます。具体的には、基本的なコードの書き方、コンパイルの方法、プログラムの実行方法に加え、数値計算の基礎となる四則演算やDOループ、IF文について学びます。
最近では、プログラミングを効率的に学習するためにAIの支援を受けることも有用です。本サイトの解説記事「ChatGPTを活用したプログラミング学習効率化」も参考にしてください。
まず初めに、Fortranプログラムをコンピュータ上で実行するための基本的な手順について見てみましょう。Fortranのプログラムは次のような手順で実行することが出来ます。
.f90
を拡張子に持つコードを書く。このFortranプログラム実行手順を学ぶために、ここでは"Hello world"プログラムと呼ばれる有名なプログラムのコードを書いて実行してみます。"Hello world"プログラムは、新しくプログラミングを学ぶときに用いられる典型的なプログラムで、最も有名なプログラムの一つです。(参考:Wikipedia)
.f90
を拡張子に持つコードを書く。まず初めに、好きなエディター(Emacs, vim, メモ帳やサクラエディタなど)を使って、次のFortranコードを書き、ファイル名をlesson0_1.f90
として保存してください
program main
write(*,*)"Hello world!!"
end program main
最初の行のprogram main
はプログラムの書き始めを示す文で、対となるend program main
という文までプログラムが上から順番に実行されていきます。ここで main
はプログラムの名前で、好きな名前を付けることが出来ます。簡単のため、ここではmain
という名前を使っています。2行目のwrite(*,*)"Hello world!!"
という文は"Hello world!!"という文字列を出力せよという命令文です。ここで使われているwrite
は、様々な結果を出力する際に良く用いられる命令文です。
上記のFortranコード (lesson0_1.f90
) の準備が出来たら、次にこのコードをコンパイルし、コンピュータが実行できる実行ファイルを作ります。下記のコマンドを端末上で打ち込むことで、コンパイルを実行しコードから実行ファイルを作ることが出来ます:
gfortran lesson0_1.f90 -o hello
ここではgfortran
コンパイラが利用されていますが、代わりに好きなコンパイラを使っても構いません。上記のコマンドにより、Fortranのソースファイル (lesson0_1.f90
)がコンパイルされ、実行ファイル(hello
)が作られます。実行ファイルの名前は、コンパイル時のオプション(-o
)を使って指定することが出来、hello
以外の好きな名前を使うことが出来ます。
上記の実行ファイル(hello
)が準備できたら、次のその実行ファイルを、下記のコマンドを打ち込んで実行します:
./hello
その結果、端末上に次の文字列が出力されます:
Hello World!!
この出力結果は、上記のコードlesson0_1.f90の2行目の文write(*,*)"Hello world!!"
によって出力されています。
ここで学んだFortranプログラミングについておさらいすると、次の3つのステップでFortranプログラムを実行することが出来ます: (i) Fortran言語で.f90
の拡張子を持つコードを書く。 (ii) Fortranのソースコードをコンパイルし、実行ファイルを生成する。 (iii) 実行ファイルを実行し、結果を得る。これが一般的なFortranプログラミングのプロセスで、以降は、同様のプロセスを他のプログラム事例について繰り返し見ていきます。
ほぼ全ての数値計算手法・コードは四則演算(和差積商)などの基礎的な数学演算の組み合わせによって実現されています。ここでは、このような基礎的な数学演算(四則演算、べき乗)について学びます。まず、次のサンプルプログラムを見てみましょう。
program main
implicit none
real(8) :: a,b,c,d,e,f,g
a = 2.0d0
b = 3.0d0
write(*,*)"a=",a
write(*,*)"b=",b
c = a + b
d = a - b
e = a * b
f = a / b
g = a**b
write(*,*)"a+b =",c
write(*,*)"a-b =",d
write(*,*)"a*b =",e
write(*,*)"a/b =",f
write(*,*)"a**b=",g
end program main
このプログラムでは、変数a
とb
に対して、四則演算(足し算、引き算、掛け算、割り算)に加えて、べき乗の計算を行っています。上記のLesson 0-1で見たのと同様に、このプログラムもprogram
文から始まっており、end program
文で終了しており、この二つの文で囲まれた範囲の命令が上から順番に実行されます。
このprogram
文の次の行で、implicit none
文を宣言しています。このimplicit none
文を宣言すると、次に述べる暗黙の型宣言を無効化することが出来ます。暗黙の型宣言とは、Fortran言語の初期設定の変数型を利用するもので、変数名がi,j,k,l
から始まる変数は整数型の変数として扱われ、それ以外の変数は実数型の変数として扱われます。この暗黙の型宣言を利用すると、プログラムに意図しないバグが入り込むリスクが増えるので、新たにプログラムを書くときは必ずimplicit none
文を宣言し、この暗黙の型宣言を無効化するようにしておきましょう。
次に、implicit none
文の下で、次のような文により変数(a-g
)を定義しています:
real(8) :: a,b,c,d,e,f,g
ここで、変数の型がreal(8)
によって定義されています。このreal(8)
は倍精度実数と呼ばれる型で、おおよそ16桁の精度を持った実数として扱われます。上のプログラムの宣言文では、7つの変数(a,b,c,d,e,f,g
)が倍精度実数型変数(real(8)
)として宣言されています。
この倍精度実数のほかにも、整数型integer
や倍精度複素数complex(8)
などの型を使うことが出来ます。
上記の変数の型宣言の後、次のようなコードを確認できます:
a = 2.0d0
b = 3.0d0
ここで, 2.0d0
は倍精度実数の数値, \(2.0\times 10^0\), を表しています。例えば、\(3.9\times 10^2\)という値の倍精度実数を使いたい場合、3.9d2
と表現することが出来ます。上のコードでは、\(2.0\times 10^0\)という値を変数a
に、\(3.0\times 10^0\)という値を変数b
にそれぞれ代入しています。Fortran言語では、等号の記号(=
)は等価性ではなく、代入操作の演算子として用いられます。
プログラム8,9行目では、変数a,b
に代入した数値を画面に出力しています:
write(*,*)"a=",a
write(*,*)"b=",b
ここでは、write
文を用いて変数の出力を行っています。このwrite文は上のLesson 0-1でも用いられています。上記の、Hello worldプログラムの例とは異なり、本例題では文字変数と実数変数の出力が行われています。Fortranでは、文字列を表すために、ダブルクォーテーション(")で文字列を囲って表現することが出来ます。例えば上のコード(lesson0_2.f90)の例では、文字列a=
は、コード内で"a="
と表されています。この表現方法は、上記のa
とb
も出力しています。
次に、実際に計算を行っている部分のコードについて見てみましょう。上のプログラムの11行目から15行目では、変数a,b
を用いて四則演算やべき乗の計算を行っています。
c = a + b
d = a - b
e = a * b
f = a / b
g = a**b
ここでは、倍精度実数変数に対して基本的な数学演算が行われており、その計算結果を倍精度実数変数であるc,d,e,f,g
に代入しています。Fortran言語では、+
記号は加算(足し算)を表し、-
記号は減算(引き算)を表し、*
記号は乗算(掛け算)を表し、/
記号は除算(割り算)を表します。また、**
記号はべき乗を表します。これらの演算を行った後に、本例題ではwrite
文を使ってその結果を出力しています。
次に、プログラムをコンパイルし実行してみましょう。コンパイルを行うために、ターミナル上で次のコマンドを実行してみます::
gfortran lesson0_2.f90 -o lesson0_2
また、コンパイルが終了した後、実行ファイルを次のように実行してみます。
./lesson0_2
すると、次のような計算結果が画面に出力されるはずです:
a= 2.0000000000000000
b= 3.0000000000000000
a+b = 5.0000000000000000
a-b = -1.0000000000000000
a*b = 6.0000000000000000
a/b = 0.66666666666666663
a**b= 8.0000000000000000
これらの結果は、あなたが予測したものと一致しているでしょうか?また、上記のプログラムで倍精度実数変数a
やb
に代入する数を変えて、結果がどう変わるかを試してみましょう。
多くの数値計算法において、決められた手続きを繰り返し反復で実行することが必要となることがしばしばあります。Fortran言語では、そのような反復処理を行うためにdo
ループと呼ばれる機能が実装されています。本節では、このdo
ループの使い方について学んでいきます。
ここでは、do
ループを学ぶための例題として、\(1\)から\(10\)までの整数の和を計算するプログラムを考えます。この問題の答えは、次のような簡単な公式で求めることが出来ます:
\[ S=1+2+3+\cdots+n = \frac{1}{2}n(n+1). \tag{1} \]
この整数の和を、do
ループを使ったプログラムによって数値的に求めるために、次のようなプログラムを考えてみましょう。
program main
implicit none
integer :: i, n, sum
n = 10
sum = 0
do i = 1, n
sum = sum + i
end do
write(*,*)"calculated sum =",sum
write(*,*)"expected sum =",n*(n+1)/2
end program main
上のコードではまず3行目で、整数型変数i, n, sum
を次のような文で定義しています:
integer :: i, n, sum
次に、コードの5行目で、1からいくつまでの整数の和を計算するかを表す整数n
を与えています。ここでは、n
を10
と設定しています。
さらに、6行目では和を計算した値を格納する変数sum
に対し、sum=0
によってゼロの値を入れることで初期化しています。変数は、宣言文で宣言されただけだと再現性のないランダムな値を持っていることがあります。したがって、必要に応じて、明示的にゼロ等の値を代入することで変数の初期化を行う必要があります。
次に7行目から、do
ループのブロックに移ります。do
ループのブロックはdo
文から始まりend do
文で終わります。do
ループは、do
ブロックの中にある手続きを繰り返し行います。コードで示されているように、do
文は整数変数と一緒に用いられます:
do i = 1, n
ここで, i
は整数型変数であり、do
ループの反復回数を制御するために用いられるループカウンターと呼ばれます。この行では、ループカウンターである整数i
をまず1
に初期化しています。do
文とend do
文に囲まれたdo
ブロック内の手続きが切り返し行われ、繰り返しのたびにループカウンター1
ずつ増加していきます(i=i+1
)。このループカウンターi
がn
を超えるまでdo
ブロックの手続きが繰り返され、i
がn
を超えた時点でdo
ループが修了します。上のプログラムでは、ループカウンターi
が1
からn
まで増加し、その間、整数型変数であるsum
にループカウンターの値i
が足し上げられていきます。ここでsum = sum + i
は、もともとのsum
の値にi
を足したものを新たなsum
の値に代入することを表しています。
それでは、上のプログラム(lesson0_3.f90)をコンパイルし実行してみましょう。次のような結果が得られるはずです。
calculated sum = 55
expected sum = 55
ここで、calculated sum
は上記のプログラムによって1
から10
までの数値を足した値が示されていますが、expected sum
は上記の公式(\(1\))によって計算された値が示されています。したがって、ここではプログラムによって計算された和が正しく数学的に導かれた公式の値を再現していることが確認できます。
数値計算を実行する際に、与えられた条件ごとに異なる処理が必要となる場合があります。そのような場合にはif
文を利用して、条件分岐を行うことが出来ます。このようなif
文の機能を理解するために、次のFortranコードを見てみましょう。
program main
implicit none
real(8) :: a, b
a = 2d0
b = 3d0
write(*,*)"a=",a
write(*,*)"b=",b
if(a == b)then
write(*,*)"a==b"
else if(a > b)then
write(*,*)"a>b"
else
write(*,*)"a<b"
end if
end program main
上記のプログラムでは、11行目のif(a == b)then
文によってa
とb
が等しいかの判定を行い、a
とb
が等しい場合は、その下のwrite(*,*)"a==b"
によって、"a==b"という文字列を画面に表示します。この場合、if
文の他の処理は行われず、end if
文まで移動して条件分岐の処理を終えます。
最初の条件文if(a == b)then
で与えられた条件に当てはまらなかった場合、次の条件文へと移動します。上のコードでは、else if(a > b)then
によってa
がb
よりも大きいかどうかの判定をおこなっており、a
がb
よりも大きい場合は、write(*,*)"a>b"
文によって"a>b"という文字列を出力を行い、end if
文まで移動します。このようにelse if (条件式) then
を用いることで、何重にも条件判定を行うことが出来ます。
ここまでの説明では、判定条件に合致した場合に処理が行われるものについて説明してきましたが、条件に当てはまらなかった場合の処理(例外処理)もプログラミングでは重要となります。上記のプログラムでは、if(a == b)then
文やelse if(a > b)then
文の後にelse
文が続いていします。このelse
文は、ここにたどり着くまでの条件判定でどれにも当てはまらなかった場合に行われる処理を記述します。上記のプログラムの例では、それまでの条件判定でa
とb
が等しくなく、さらにa
がb
よりも大きくないことも分かっているので、a
がb
よりも小さいことを表す"a<b"
を画面に出力してif
文の処理を終えています。
if
文には様々な条件式を使うことが出来ますが、多くの場合は下記のような条件を知っていればプログラムを書くことが出来ます。
a==b
: a
とb
が等しい。a>b
: a
がb
より大きい。a<b
: a
がb
より小さい。a>=b
: a
がb
より大きい、または等しい。a<=b
: a
がb
より小さい、または等しい。a/=b
: a
とb
が等しくない。このページではFortranプログラミングの基礎について学びました。次のページではFortranを用いた数値微分について学びます。
Fortranで数値微分