Fortranにおける数の精度について
題名の通り,Fortranでの数の精度について調べてみた.
自分では実数の時はただdouble precisionとしていた.一方で複素数のときにはcomplex(kind(0d0))としていたが,統一的な書式で書きたいと思ったためだ.
reald(8)とcomplex(8)でもよかったのだが,括弧の意味がコンパイラで変わるということも見かける(参考ページ1)ので,kindの意味について調べることにした.
使うのはselected_real_kindというコマンドで,第1引数に桁数,第2引数に指数範囲を代入する.別のページで第3引数も見た気がするが,この2つ,もっと言えば第1引数の桁数のみで十分だと思う.
サンプルプログラムは参考ページ3のそれをいじった次のようなもの.ただひたすらに様々なパターンを突っ込んで実行するのみ.
program real_kinds real :: x0 real(8) :: x1 double precision :: x2 real(kind(0d0)) :: x3 integer, parameter :: p6 = selected_real_kind(6) integer, parameter :: p6r50 = selected_real_kind(6,50) integer, parameter :: p12 = selected_real_kind(10) integer, parameter :: r400 = selected_real_kind(r=400) integer, parameter :: p33 = selected_real_kind(33) real(kind=p6) :: x4 real(kind=p6r50) :: x5 real(kind=p10r50) :: x6 real(kind=r400) :: x7 print *, precision(x0), range(x0) print *, precision(x1), range(x1) print *, precision(x2), range(x2) print *, precision(x3), range(x3) print *, precision(x4), range(x4) print *, precision(x5), range(x5) print *, precision(x6), range(x6) print *, precision(x7), range(x7) print *, precision(x8), range(x8) end program real_kinds
そして実行結果は
6 37 15 307 15 307 15 307 6 37 15 307 15 307 33 4931 33 4931
という感じ.スペースがあるのはそのまま貼り付けたため.
参考ページに書いてあることと,上の実行結果から分かることとしては,
- 桁数だけを入力すればその桁数を満たすなかで最低限の精度が返ってくる.
- 指数範囲だけを入力しても同様.
- 両方指定した場合は両方を満たす最低限の精度が返ってくる.
- realとすると,桁数は6で指数範囲は37.
- real(8), double precision, real(kind=0d0)では桁数15で指数範囲307.
- これらの精度を越えようとすると,桁数は33で指数範囲は4931になる.これ以上はない(エラーが返ってくる)
- 複素数については同じものがそのまま使える模様(実数2つの配列のようなものだから当然かもしれないが)
まとめとしては,
- 特に気にせずdouble precisionやreal(8)を使っている場合は,有効桁数は15になる.
- もしこれを越えたければ,selected_real_kind(33)など,コンパイラに応じた最大桁数にすればよい.
といったところだろうか.
参考ページ