[Fortran]write文で出力時に改行させない
$かadvanceオプションにnoを指定する。
write(*,'(a)') 'AB'
write(*,'(a)') 'CD'
write(*,'(a,$)') '12'
write(*,'(a)') '34'
write(*,'(a)',advance='no') '56'
write(*,'(a)') '78'
end
実行結果
>a.exe
AB
CD
1234
5678
GNU Fortran 8.2.0で動作確認をしている。
$かadvanceオプションにnoを指定する。
write(*,'(a)') 'AB'
write(*,'(a)') 'CD'
write(*,'(a,$)') '12'
write(*,'(a)') '34'
write(*,'(a)',advance='no') '56'
write(*,'(a)') '78'
end
実行結果
>a.exe
AB
CD
1234
5678
GNU Fortran 8.2.0で動作確認をしている。
external文を使用すると、サブルーチンの引数に変数や配列以外に、サブルーチンを指定することもできる。以下はWindowsのgfortranで実行した例。説明を簡単にするために、簡略化して記述しているので注意。
メインルーチンで、サブルーチンsub1を呼び出しているが、そのsub1を呼び出し時に、引数にsub2を指定し、sub1ではその指定されたsub2をさらに呼び出している。メインルーチンで、呼び出される側で呼び出すサブルーチンをexternal文で指定しておく必要がある。
external sub2
call sub1(sub2, 10)
end
subroutine sub1(sname, n)
integer n
write(*, '(a,1x,i3)') 'A', n + 1
call sname(n + 2)
write(*, '(a,1x,i3)') 'C', n + 3
end subroutine
subroutine sub2(n)
integer n
write(*, '(a,1x,i3)') 'B', n
end subroutine
実行結果
>a.exe
A 11
B 12
C 13
access関数を使う。第一引数に存在の有無を確認したいファイル名かディレクトリ名。第二引数に「r」を指定する。第一引数に指定をしたファイル(ディレクトリ)が存在した場合は0、存在しない場合は0以外を返す。
program test
implicit none
integer n
n = access('C:\Windows', 'r')
print *, n
n = access('C:\Win', 'r')
print *, n
n = access('C:\Windows\write.exe', 'r')
print *, n
n = access('C:\Windows\wri.exe', 'r')
print *, n
n = access('C:\Windows\', 'r')
print *, n
n = access('C:\Windows\write.exe\', 'r')
print *, n
end program test
出力結果(環境により異なる)。
>test.exe
0
2
0
2
0
22
ファイルかディレクトリの判別は、上記の最後2つの例のとおりに、第一引数のパスの最後にパス区切り文字(ウィンドウズの場合は¥)を付ける。パス区切り文字を最後に付けると、それはディレクトリと判断して存在の有無が確認される。
access関数はGNU拡張機能(GNU extension)であることに注意。
gfortranの古いバージョンにはバグがあり、ブログラムに間違いがなくても、このエラーメッセージが表示されることがある。
>a.exe
Program received signal SIGSEGV: Segmentation fault - invalid memory reference.
Backtrace for this error:
#0 ○○
(以下、表示省略)
ソースコードに誤りがなくてもこのメッセージが表示される場合は、gfortranのバージョンを上げてみる。例えば、以下のバージョンだと、このエラーメッセージが表示されることが多いようだ。
>gfortran --version
GNU Fortran (MinGW.org GCC-6.3.0-1) 6.3.0
2020年7月時点の最新バージョンは以下のとおり。
>gfortran --version
GNU Fortran (MinGW.org GCC Build-20200227-1) 9.2.0
このバージョンでは、上記のエラーメッセージが表示されることは少ないはず。
Fortranの配列の要素番号(インデックス)は、通常は1~であり、値を取り出すために指定をするインデックスは自然数で指定することになる。しかし、デフォルトでは、このインデックスの指定のチェックは甘い。例えば以下のソースコードを実行してみる。
implicit none
integer a, b
dimension a(3)
a(1) = 1
b = 0
a(2) = a(b)
b = -1
a(3) = a(b)
write(*,'(3(I3,1X))') a(1),a(2),a(3)
end
実行すると、以下のようになる。
>gfortran.exe -o array.exe array.f
>array.exe
1 0 0
配列aのインデックスに0や-1を指定しているのに、値が取り出せてしまっている。これを防ぐためには、コンパイル時に-fbounds-checkオプションを使用する。
>gfortran.exe -fbounds-check -o array.exe array.f
>array.exe
At line 6 of file array.f
Fortran runtime error: Index '0' of dimension 1 of array 'a' below lower bound of 1
Error termination. Backtrace:
Could not print backtrace: libbacktrace could not find executable to open
(以下省略)
配列のインデックスに0を指定していることが、実行時にチェックされており、この例ではプログラムが緊急停止していることがわかる。なお、上記のことは以下のコンパイラーで実行している。環境はWindows。
>gfortran --version
GNU Fortran (MinGW.org GCC-8.2.0-3) 8.2.0
program test
write(*,*) int(2.4d0)
write(*,*) int(2.5d0)
write(*,*) int(2.6d0)
write(*,*) int(-2.4d0)
write(*,*) int(-2.5d0)
write(*,*) int(-2.6d0)
end program
2
2
2
-2
-2
-2
上記のとおり、単純に小数点以下を切り捨てているだけである。0に近い値へ寄せるようなことなどはしていない。
MinGWを使えば、Windows 8.1で無料で使えるFortranコンパイラーが使える。
以下のページを開く。
http://www.mingw.org/wiki/msys
左側のメニュー、「Navigation」→「Downloads」をクリック。sourceforgeのページに飛ぶ。
いろいろ表示されているが、「Looking for the latest version?」とある隣の「Download mingw-get-setup.exe (86.5 kB)」をクリックして、mingw-get-setup.exeをダウンロードする。なお、これは各種プログラムをダウンロードするだけのプログラム(インストーラー)に過ぎない。
ダウンロードしたmingw-get-setup.exeを起動する。C:\MinGWにインストールしようとするので、インストーラーの指示に従ってインストールする。
デスクトップにアイコン「MinGW Installer」が作成されたはず。これをダブルクリックして、MinGW Installerを起動する。
左側のメニュー「Basic Setup」をクリックすると、右側上部にいろいろ表示されるが、「mingw32-base」、「mingw32-gcc-fortran」、「mingw32-gcc-g++」の3つのパッケージがあるはず。これを選択する(右クリックで現れたメニューから「Mark for Installation」をクリック)。
上部のメニュー「Installation」→「Apply Changes」を選択し、現れたダイアログのボタン「Apply」をクリックすると、インストールが始まる。
パスを通す。環境変数PathにC:\MinGW\binを追加する。
Fortranの組み込み関数(Fortranに標準で搭載されている関数)には個別名と総称名を持つものがある。具体的にはdsinとsin、dabsとabsなどである。
これらはその組み込み関数の引数と戻り値の肩に関するものである。上の例では、dsinとdabsはその関数の引数には倍精度浮動小数点型の変数しか扱えない。これらdsinやdabsといった名前を個別名と呼ぶ。
一方、sinやabsは総称名と呼ばれ、これらは関数の引数に与えられた型を自動で判定して計算し、その関数のも度値も引数で与えた型で返す。
以下は実行例。
program sosho
implicit none
real r
double precision d
r = 3.14
d = 3.14d0
print '(f20.18)', r ! 単精度定数
print '(f20.18)', d ! 倍精度定数
print '(f20.18)', sin(r) ! 単精度で計算(総称名)
print '(f20.18)', dsin(d) ! 倍精度で計算
print '(f20.18)', sin(d) ! 倍精度で計算(総称名)
end program sosho
出力は以下のとおり。
3.140000104904174805
3.140000000000000124
0.001592547981999815
0.001592652916486828
0.001592652916486828
Fortranでは浮動小数点数(※)を扱うとき、変数へ定数を代入するときには単精度が倍精度を明示しなければならない。
例えば、倍精度浮動小数点型の変数へ代入する際、数値定数を「3.14」としただけでは単精度浮動小数点数とみなされてしまう。この場合、有効桁数は6桁程度しかない。指数部に「E」あるいは「e」を使用した場合も同じ。
高精度な数値計算を行いたくて倍精度浮動小数点数で計算を行う場合は、数値定数の指数部に「D」あるいは「d」を用いた表記を使用すること。
以下の例では、倍精度浮動小数点型の変数に代入する際、数値定数の表記による数値の取扱いの差を示したもの。指数部を「d」を使用して表記しなければ倍精度で扱われていないことがわかる。
program doublecheck
implicit none
double precision d1, d2, d3
d1 = 3.14
d2 = 3.14e0
d3 = 3.14d0
print '(f20.18)', d1
print '(f20.18)', d2
print '(f20.18)', d3
end program
出力
3.140000104904174805
3.140000104904174805
3.140000000000000124
※Fortranに関する書籍では「実数」と表記するものが多いが、これは簡便な表記であり、プログラミング言語の分野では実数を「浮動小数点数」と呼ぶことが多い。
use ××
1
エラー: '○○' of module '××', imported at (1), is also the name of the current program unit
これは、プログラム名とモジュールに含まれるサブルーチン名が重複していると発生するエラー。このuse文でモジュールを呼び出すプログラムがたとえばabcというプログラムの時(最初のprogram ~の~のところがabc)、その呼び出すモジュールにabcという名前のサブルーチンが含まれている場合、このエラーメッセージが表示されてコンパイルが止まる。
解決するには、重複しているプログラム名とサブルーチン名のどちらかを変えること。