モジュール java.base
パッケージ java.lang

クラスDouble

java.lang.Object
java.lang.Number
java.lang.Double
すべての実装されたインタフェース:
Serializable, Comparable<Double>, Constable, ConstantDesc

public final class Double extends Number implements Comparable<Double>, Constable, ConstantDesc
Doubleクラスは、プリミティブ型doubleの値をオブジェクトにラップします。 Double型のオブジェクトには、型がdoubleの単一フィールドが含まれます。

さらにこのクラスは、doubleStringに、Stringdoubleに変換する各種メソッドや、doubleの処理時に役立つ定数およびメソッドも提供します。

これはvalue-basedクラスです。プログラマは、equalのインスタンスを交換可能として扱い、同期にインスタンスを使用しないようにする必要があります。そうしないと、予期しない動作が発生する可能性があります。 たとえば、将来のリリースでは、同期が失敗する可能性があります。

浮動小数点等価、等価および比較

IEEE 754浮動小数点値には、有限ゼロ以外の値、符号付きゼロ (+0.0および-0.0)、符号付きインフィニティ (「正の無限大」「負の無限大」)、およびNaN (not-a-number)が含まれます。

値セットに対する「等価関係」は、再帰的、対称的および推移的の値のペアに対するブール関係です。 等価関係とオブジェクト等価の詳細は、Object.equals仕様を参照してください。 等価関係は、操作する値を「同等クラス」というセットにパーティション化します。 等価クラスのすべてのメンバーは、関係の下で相互に等しくなります。 等価クラスには、1つのメンバーのみを含めることができます。 一部の目的では、同等クラスのすべてのメンバーが互いに置換可能です。 特に、数値の式の等価値は、式の結果を変更することなく、互いに「置き換え」にすることができます。つまり、式の結果の等価クラスを変更します。

浮動小数点値に対する組込みの==操作は、等価関係ではありません。 等価関係を定義していないにもかかわらず、IEEE 754 ==演算子のセマンティクスは、他の数値計算ニーズを満たすように意図的に設計されました。 浮動小数点値に対して ==で等価関係のプロパティが満たされないという2つの例外があります:

  • v1v2の両方がNaNの場合、v1 == v2の値はfalseです。 したがって、2つのNaN引数では、等価関係のreflexiveプロパティは==演算子によって満たされません。
  • v1+0.0を表し、v2-0.0、またはその逆の場合は、+0.0-0.0が様々な浮動小数点演算で区別される場合でも、v1 == v2の値はtrueになります。 たとえば、1.0/+0.0は正の無限大と評価され、1.0/-0.0negativeの無限大と正の無限大に評価され、負の無限大は互いに等しくありません。 したがって、符号付きゼロ入力は、通常、ゼロ結果の符号を決定します。これは、ゼロで除算すると、+0.0-0.0が一般的には相互に置換されないためです。 0(ゼロ)入力の符号は、数学ライブラリのメソッドの結果に置換えられない効果もあります。

組込みの比較演算子(<, <=, etc.)を使用した順序比較の場合、NaNの値には別の異常な状況があります: NaNは、それ自体を含め、それより小さくも、それ以上でも、どの値でもありません。 これは、「比較の抜本的な」が保持されないことを意味します。

equalsおよびcompareToメソッドに適切なセマンティクスを提供するために、これらのメソッドは、単に==または順序付けされた比較操作を囲むことはできません。 かわりに、equals「表現等価」を使用し、NaN引数を相互に等しくなるように定義し、再帰性をリストアし、+0.0-0.0と等しくないように定義します。 比較の場合、compareToは、-0.0+0.0より小さく、NaNがそれ自体と等しく、正の無限大より大きいとみなされる合計順序を定義します。

equalsおよび compareToの動作セマンティクスは、「ビット単位変換」によって整数値への浮動小数点値で表されます。

compareToによって実装される「自然順序付け」は、「等しい」です。 つまり、2つのオブジェクトがequalsと等しいとレポートされるのは、それらのオブジェクトのcompareToが0を返す場合のみです。

equalsおよび compareToに定義された調整済動作により、ラッパー・クラスのインスタンスは従来のデータ構造で適切に動作できます。 たとえば、NaNの値をequalsとして定義すると、NaNをHashSetの要素またはHashMapのキーとして使用できます。 同様に、 compareTo+0.0 -0.0、NaNなどの合計順序として定義すると、ラッパー・クラスのインスタンスをSortedSetの要素またはSortedMapのキーとして使用できます。

数値等価と、浮動小数点値に対して定義できるさまざまな有用な等価関係を比較します:

等比数列 (==演算子): (等価関係ではない)
2つの浮動小数点値は、同じ拡張実数を表します。 拡張実数は、正の無限大および負の無限大で拡張された実数です。 数値等価では、+0.0-0.0は両方とも同じ実数値0にマップされるため等しくなります。 NaNは、どの実数にもマップされず、それ自体を含むどの値にも等しくありません。
ビットごとの同等性:
2つの浮動小数点値のビットは同じです。 doubleaおよび bに対するこの等価関係は、式によって実装されます
Double.doubleTo Raw LongBits(a) == Double.doubleTo Raw LongBits(b)
この関係では、+0.0-0.0は相互に区別され、NaNのビット・パターン・エンコーディングは、NaNのその他のビット・パターン・エンコーディングとは区別されます。
表現等価:
2つの浮動小数点値は、同じIEEE 754 「データム」を表します。 特に、「有限」値の場合、浮動小数点値の符号、「指数」、および重要なコンポーネントは同じです。 この関係の下:
  • +0.0-0.0は相互に区別されます。
  • NaNのビット・パターン・エンコーディングは、相互に同等とみなされます
  • 正の無限大は正の無限大に相当し、負の無限大は負の無限大に相当します。
この等価関係を実装する式は次のとおりです:
  • Double.doubleToLongBits(a) == Double.doubleToLongBits(b)
  • Double.valueOf(a).equals(Double.valueOf(b))
  • Double.compare(a, b) == 0
表現等価性は、多くの場合、「数学ライブラリ」の動作をテストするための等価性の適切な概念です。
2つのバイナリ浮動小数点値aおよびbでは、abのどちらもゼロまたはNaNでない場合、abの3つの関係の数値等価性、ビット単位等価性および表現等価性は同じtrue/false値になります。 つまり、2進浮動小数点値の場合、少なくとも1つの引数が0またはNaNの場合のみ、3つの関係は異なります。

小数点↔バイナリ変換の問題

2進浮動小数点演算の多くの驚くべき結果は、10進から2進への変換および2進から10進への変換の側面まで遡ります。 整数値は任意の基数で正確に表すことができますが、基数で正確に表すことができる小数値は基数の関数です。 たとえば、ベース10では、1/3は繰返し小数(0.33333....)ですが、ベース3では、1/3は正確に0.1(3)、つまり1×3-1です。 同様に、基本10では、1/10は0.1 (1 × 10-1)として正確に表現できますが、基本2では繰返しfraction(0.0001100110011...(2))です。

float型の値は24ビットの精度を持ち、double型の値は53ビットの精度を持ちます。 したがって、0.1は、4ビット繰返しのベース2の繰返し分数であるため、 0.1f != 0.1dです。 16進浮動小数点リテラルを含む詳細:

  • 0.1f (0x1.99999a0000000p-4f)の正確な数値は、0.100000001490116119384765625です。
  • 0.1d (0x1.999999999999ap-4d)の正確な数値は、0.1000000000000000055511151231257827021181583404541015625です。
これらはそれぞれ、0.1の数値に最も近いfloatおよびdouble値です。 これらの結果は、小数点精度が6から9桁に相当するfloat値と、小数点精度が15から17桁に相当するdouble値と一致しています。 (等価精度は、実数行に沿った異なる点での、2進値と10進値の相対密度によって異なります。)

この表現の10進数の危険性は、金額値をfloatまたは doubleとして格納する際の注意事項を使用する理由の1つです。 代替方法は次のとおりです。

  • BigDecimalを使用して小数値を正確に格納します。
  • 金額が整数になるようにスケール・アップ - たとえば、値がセントで示されている場合は100を乗算し、値がミルで示されている場合は1000を乗算します。 - 次に、そのスケールされた値を整数型に格納します。

有限浮動小数点値と指定された浮動小数点型ごとに、その値にマップされる実数行の連続したリージョンがあります。 デフォルトの丸めから最も近い丸めポリシー(JLS 15.4)では、値のこの連続するリージョンは、通常、幅が1つのulp (最後の場所の単位)で、正確に表現可能な値を中心にしています。 (指数境界では、リージョンは非対称で、大きい指数を持つ側では大きくなります。) たとえば、0.1fの場合、リージョンは次のように計算できます。
//リストされる数値は正確な値です
oneTenthApproxAsFloat = 0.100000001490116119384765625;
ulpOfoneTenthApproxAsFloat = Math.ulp(0.1f) = 7.450580596923828125E-9;
// 0.1、_excludes_ endpoints
(oneTenthApproxAsFloat - ½ulpOfoneTenthApproxAsFloat, oneTenthApproxAsFloat + ½ulpOfoneTenthApproxAsFloat) =
(0.0999999977648258209228515625, 0.1000000052154064178466796875)に最も近いfloatに変換される数値範囲

特に、この範囲の数値を表す文字列の、正しく丸められた10進数から2進数への変換(Float.parseFloat(String)など)は、同じ値に変換されます。

Float.parseFloat("0.0999999977648258209228515625000001"); // rounds up to oneTenthApproxAsFloat
Float.parseFloat("0.099999998");                          // rounds up to oneTenthApproxAsFloat
Float.parseFloat("0.1");                                  // rounds up to oneTenthApproxAsFloat
Float.parseFloat("0.100000001490116119384765625");        // exact conversion
Float.parseFloat("0.100000005215406417846679687");        // rounds down to oneTenthApproxAsFloat
Float.parseFloat("0.100000005215406417846679687499999");  // rounds down to oneTenthApproxAsFloat

同様に、0.1dへのdouble近似値と Math.ulp(0.1d)の数値、およびfloat型とdouble型のその他の特定の数値に基づいて、 double型に類似した範囲を構築できます。

前述の変換に示すように、丸めなしで操作が持つ正確な数値と比較すると、結果として同じ浮動小数点値は次のようになります。

  • 正確な結果より大きい
  • 正確な結果と等しい
  • 正確な結果より小さい
浮動小数点値は、丸めの結果であったか、丸めの結果であったか、正確な操作であったかに関係なく"知る"ではなく、計算方法の履歴は含まれません。 その結果、
0.1f + 0.1f + 0.1f + 0.1f + 0.1f + 0.1f + 0.1f + 0.1f + 0.1f + 0.1f;
// Numerical value of computed sum: 1.00000011920928955078125,
// the next floating-point value larger than 1.0f, equal to Math.nextUp(1.0f).
or
0.1d + 0.1d + 0.1d + 0.1d + 0.1d + 0.1d + 0.1d + 0.1d + 0.1d + 0.1d;
// Numerical value of computed sum: 0.99999999999999988897769753748434595763683319091796875,
// the next floating-point value smaller than 1.0d, equal to Math.nextDown(1.0d).
1.0と正確には等しくなるべきではなく、1.0に近いものにしてください。 その結果、次のコードは無限ループになります。
double d = 0.0;
while (d != 1.0) { // Surprising infinite loop
  d += 0.1; // Sum never _exactly_ equals 1.0
}
代わりに、カウントされたループに整数ループ数を使用します。
double d = 0.0;
for (int i = 0; i < 10; i++) {
  d += 0.1;
} // Value of d is equal to Math.nextDown(1.0).
または、順序付き比較(<, <=, >, >=)を使用して浮動小数点制限に対してテストします。
double d = 0.0;
while (d <= 1.0) {
  d += 0.1;
} // Value of d approximately 1.0999999999999999
浮動小数点演算は驚くべき結果をもたらすかもしれませんが、IEEE 754浮動小数点演算は原則的な設計に従い、その動作はJavaプラットフォームで予測可能です。

Java言語仕様を参照してください:
「4.2.3 浮動小数点型、形式および値」
「4.2.4.浮動小数点演算」
「15.21.1 数値等価演算子==と!=」
「15.20.1 数値比較演算子<<=>および>=
導入されたバージョン:
1.0
関連項目: