akios @ ウィキ
4.2.3. 浮動小数点型と書式と値
最終更新:
akios
-
view
4. 型と値と変数
4.1. 型と変数の種類
4.2. プリミティブ型と値
4.2.1. 整数型と値
4.2.2. 整数演算
4.2.3. 浮動小数点型と書式と値
浮動小数点型(floating-point type)にはfloat、doubleがあり、それぞれが2進浮動小数点計算のためのIEEE規格、ANSI/IEEE規格754-2008(IEEE, New York)、で規定する単精度32ビット、倍精度64ビット形式のIEEE754値および演算に概念的に関連づいています。
IEEE754規格には符号と数の大きさからなる正と負の数だけでなく正と負のゼロ、正と負の無限大、特別な非数値(Not-a-Number、以降NaN)も含まれています。NaN値はゼロ割るゼロ等の無効な演算の結果を表すのに利用されます。NaNはFloat.NaNやDouble.NaNとしてfloat型にもdouble型にもそれぞれ組み込まれています。
Javaプログラミング言語のどの実装も浮動小数点値の2つの標準集合、float値集合とdouble値集合をサポートしています。加えて、Javaプログラミング言語の実装は、float拡張指数値集合やdouble拡張指数値集合と呼ばれる2つの拡張指数集合の片方もしくは両方を任意でサポートします。この拡張指数値集合は、特定の環境下で、標準値集合の代わりにfloatやdouble型の式の値を表すのにしようされます(5.1.13.、15.4.)。
任意の浮動小数点値集合の有限非ゼロ値は全てs・m・2(e - N + 1)の形で表されます。ここで、sは+1もしくは-1、mは2N未満の正の整数、eはEmin = -(2K-1-2)以上Emax=(2K-1-1)以下の整数で、NとKは値集合に依存するパラメーターです。値によってはこの形式内で複数の形で表すことができます。例えば、値集合内の値vを適当なs、m、eを使って表したとします。次にmは偶数でeは2K-1未満ならば、半分のmとeに1を足すことで同一の値vを第2の形で表すことができます。m≧2N-1の時、この形式の表現を正規化されている(normalized)と呼びます。そうでなければ非正規化されている(denormalized)と呼びます。値集合の値がm≧2N-1の形で表せない場合、正規化表現を持たないことから、非正規化値と呼びます。
2つの必須の浮動小数点値集合とオプションの2つの浮動小数点値集合について、パラメーターNとK(およびそれから導出されるパラメーターEminとEmax)の条件を表4.1.にまとめます。
表4.1. 浮動小数点値集合パラメーター
パラメーター | float | float拡張指数 | double | double拡張指数 |
N | 24 | 24 | 53 | 53 |
K | 8 | ≧11 | 11 | ≧15 |
Emax | +127 | ≧+1023 | +1023 | ≧+16363 |
Emin | -126 | ≦-1022 | -1022 | ≦-16382 |
片方もしくは両方の拡張指数値集合が実装でサポートされている時、サポートされている拡張指数値集合のそれぞれに対して特別な実装依存定数Kがあります。この値は表4.1.の条件を満たし、そしてKはEminとEmaxに影響を及ぼす。
4つの値集合のどれも上記で記述した有限非ゼロ値だけでなくNaN値や正のゼロ、負のゼロ、正の無限大、負の無限大の4つの値を含んでいます。
表4.1.はfloat値集合の全要素はfloat拡張指数値集合、double値集合、double拡張指数値集合の要素でもあることが条件であるように設計されています。同様に、double値集合の各要素はdouble拡張指数値集合の要素でもあることも条件です。どの拡張指数値集合も対応する標準値集合より指数範囲は大きくなっていますが、精度は同じです。
float値集合の要素はIEEE754規格で定義されている単精度浮動小数点形式を使って表せる値と正確に同じです。double値集合の要素はIEEE754規格で定義されている倍精度浮動小数点形式を使って表せる値と正確に同じです。ただし、float拡張指数値集合とdouble拡張指数値集合の要素はIEEE754単精度拡張形式や倍精度拡張形式を使って表せる値とは一致しません。
float、float拡張指数、double、double拡張指数値集合は型ではありません。Javaプログラミング言語の実装がfloat型の値を表すためにfloat値集合の要素を用いるのは常に正しいことです。しかしながら、実装のある領域でfloat拡張指数値集合の要素を代わりに用いるのは許されています。同様に、実装がdouble型の値を表すためにdouble値集合の要素を用いるのは常に正しいことです。しかしながら、実装のある領域でdouble拡張指数値集合の要素を代わりに用いるのは許されています。
NaNを除いて、浮動小数点値は順序づけられています。小さいものから大きなものへ、負の無限大、負の有限非ゼロ値、正と負のゼロ、正の非有限ゼロ値、正の無限大という順序です。
IEEE754は単精度、倍精度浮動小数点形式のいずれにおいても複数の異なるNaN値を持つことを認めています。個々のハードウェアアーキテクチャーによって新たなNaNの発生に対してNaNがある特定のビットパターンを返すと決まっているとしても、例えば遡及的診断情報(retrospectivge diagnostic information)を符号化するために、プログラマーは異なるビットパターンのNaNを作成することができます。
大抵、Java SEプラットフォームは与えられた型のNaN値をあたかも単一の正規化値にまとめてられているように扱います。よって本仕様では通常、任意のNaNをあたかも1つの正規化値のように参照します。
しかしながら、Java SEプラットフォームのバージョン1.3でプログラマーがNaN値の違いを区別できるようなメソッドが導入されました。Float.floatToRawIntBitsとDouble.doubleToRawLongBitsメソッドです。更なる情報に興味のある読者はFloatやDoubleクラスの仕様を参照してください。
正のゼロと負のゼロを比較する場合それらは等価です。よって、式0.0==-0.0の結果はtrueであり0.0>-0.0の結果はfalseです。しかし他の演算では正のゼロと負のゼロは区別されます。例えば、1.0/0.0の値は正の無限大ですが、1.0/-0.0は負の無限大です。
NaNは順序付けされないので、以下が成り立ちます。:
- 数値比較演算子<と<=と>と>=は一方もしくは両方のオペランドがNaNであればfalseを返します。
- 等価演算子==は一方のオペランドがNaNであればfalseを返します。
特に、(x<y) == !(x>=y)はxかyの一方がNaNであればfalseです。
- 不等価演算子!=は一方のオペランドがNaNであればtrueを返します。
特に、x!=xはxがNaNである場合のみtrueを返します。