浮動小数点数

環境依存のパラメータ

浮動小数点数の精度や値の範囲などの環境依存のパラメータを得るためにはMACHAR関数を使う。現行バージョンのIDLがサポートしているプラットフォームでは、だいたい同じ結果になるはず。例外はIRNDで、 Windows、Linux、Mac (Intel)版IDLでは IRND=5 (漸次アンダーフロー; gradual underflow が行われる), Solaris (SPARC)版IDLでは IRND=2 (flush to zero が行われる) となる。なお、いずれの場合も、XMINは正規化数の最小値を示す。以下は、IDL 8.2 (linux x86_64 m64) での実行結果。

  1. IDL> HELP, MACHAR()
  2. ** Structure MACHAR, 13 tags, length=52, data length=52:
  3. IBETA LONG 2
  4. IT LONG 24
  5. IRND LONG 5
  6. NGRD LONG 0
  7. MACHEP LONG -23
  8. NEGEP LONG -24
  9. IEXP LONG 8
  10. MINEXP LONG -126
  11. MAXEXP LONG 128
  12. EPS FLOAT 1.19209e-07
  13. EPSNEG FLOAT 5.96046e-08
  14. XMIN FLOAT 1.17549e-38
  15. XMAX FLOAT 3.40282e+38
  16. IDL> HELP, MACHAR(/DOUBLE)
  17. ** Structure DMACHAR, 13 tags, length=72, data length=68:
  18. IBETA LONG 2
  19. IT LONG 53
  20. IRND LONG 5
  21. NGRD LONG 0
  22. MACHEP LONG -52
  23. NEGEP LONG -53
  24. IEXP LONG 11
  25. MINEXP LONG -1022
  26. MAXEXP LONG 1024
  27. EPS DOUBLE 2.2204460e-16
  28. EPSNEG DOUBLE 1.1102230e-16
  29. XMIN DOUBLE 2.2250739e-308
  30. XMAX DOUBLE 1.7976931e+308

特殊な値

無限大

無限大を得るにはシステム定数 !VALUES.F_INFINITY (FLOAT型)、!VALUES.D_INFINITY (DOUBLE型)を使う。

与えられた値が無限大かどうかを判別するには FINITE(/INFINITY) 関数を使う。SIGN キーワードで符号を判別できる。

非数

非数を得るにはシステム定数 !VALUES.F_NAN (FLOAT型)、!VALUES.D_NAN (DOUBLE型)を使う。

与えられた値が非数かどうかを判別するには FINITE(/NAN) 関数を使う。SIGN キーワードで符号を判別できる。

  1. IDL> a = [!values.f_infinity, -!values.f_infinity, !values.f_nan, -!values.f_nan]
  2. ; 無限大・非数でないとき真
  3. IDL> print, finite(a)
  4. 0 0 0 0
  5. ; 非数のとき真
  6. IDL> print, finite(a, /nan)
  7. 0 0 1 1
  8. ; 無限大のとき真
  9. IDL> print, finite(a, /infinity)
  10. 1 1 0 0
  11. ; 正の無限大のとき真
  12. IDL> print, finite(a, /infinity, sign = 1)
  13. 1 0 0 0
  14. ; 負の無限大のとき真
  15. IDL> print, finite(a, /infinity, sign = -1)
  16. 0 1 0 0

IDL 8.4以降では次のよう IDL_Variable クラスの静的メソッドを用いても書ける。ただし、配列に対してして行う場合、全ての要素について条件を満たすときのみ1を返す。

  1. IDL> a = [!values.f_infinity, 1, 2, 3]
  2. IDL> b = [!values.f_nan, 4, 5, 6]
  3. ; 全ての要素が無限大・非数でないとき真
  4. IDL> print, a.IsFinite(), b.IsFinite()
  5. 0 0
  6. ; 全ての要素が非数のとき真
  7. IDL> print, a.IsNaN(), b.IsNaN()
  8. 0 0
  9. ; 全ての要素が無限大のとき真
  10. IDL> print, a.IsInfinite(), b.IsInfinite()
  11. 0 0
  12. ; 有限の要素のみ返す
  13. IDL> print, a.Finite(), b.Finite()
  14. 1.00000 2.00000 3.00000
  15. 4.00000 5.00000 6.00000

算術例外

0除算などの算術例外を報告するタイミングを変更するには !EXCEPT システム変数を変更する。デフォルト値は !EXCEPT = 1 で、サブルーチン中で算術例外が発生した場合でも、サブルーチン終了後に算術例外が報告される。!EXCEPT = 2 にすると、算術例外が発生すると即座に報告されるが、パフォーマンスは低下する。!EXCEPT = 0 では算術例外を一切報告しない。

  1. !EXCEPT = 1 ; default
  2. print, 1/0, 1.0/0
  3. print, !values.f_infinity - !values.f_infinity
  4. end

上記のプログラムを実行すると、算術例外は最後にまとめて報告される。

  1. 1 Inf
  2. -NaN
  3. % Program caused arithmetic error: Integer divide by 0
  4. % Program caused arithmetic error: Floating divide by 0
  5. % Program caused arithmetic error: Floating illegal operand
  1. !EXCEPT = 2
  2. print, 1/0, 1.0/0
  3. print, !values.f_infinity - !values.f_infinity
  4. end

上記のプログラムを実行すると、算術例外が発生する度に報告されるため、発生箇所を容易に特定できる。

  1. 1 Inf
  2. % Program caused arithmetic error: Integer divide by 0
  3. % Program caused arithmetic error: Floating divide by 0
  4. % Detected at $MAIN$ 2 /dev/tty
  5. -NaN
  6. % Program caused arithmetic error: Floating illegal operand
  7. % Detected at $MAIN$ 3 /dev/tty

算術例外が発生したかどうかを調べるには CHECK_MATH 関数を用いる。ただし、IDLが算術例外を報告するタイミングで、CHECK_MATH 関数の返す結果も0にリセットされる。つまり、!EXCEPT = 1 のとき、プログラムが終了し、インタラクティブコマンドプロンプトに戻ると結果はリセットされる。!EXCEPT = 2 のときには、プログラムの実行が次のステートメントに移ると結果はリセットされる。

内部表現

浮動小数点数の内部表現を変換するには BYTEORDER プロシージャを用いる。単にエンディアンを変換するだけなら、SWAP_ENDIAN 関数か SWAP_ENDIAN_INPLACE プロシージャも利用可能。

西田圭佑 (NISHIDA Keisuke)
nishida at kwasan.kyoto-u.ac.jp