このコード
Double dbl = 254.9999999999999;
Integer integ = dbl.intValue();
System.out.println(integ);
254を示していますが、さらに1つの「9」
Double dbl = 254.99999999999999;
Integer integ = dbl.intValue();
System.out.println(integ);
そしてそれはすでに255です..なぜですか?
ダブルの正確な値を知るには、BigDecimalを使用できます。
System.out.println(new BigDecimal(254.9999999999999));
System.out.println(new BigDecimal(254.99999999999999));
プリント:
254.9999999999998863131622783839702606201171875
255
したがって、これは単に倍精度(の制限)によるものです...
System.out.println(254.9999999999999 == 255.0);
System.out.println(254.99999999999999 == 255.0);
プリント
false
true
それはあなたにヒントを与えるはずです。 double
型は最大16桁の有効数字を表すことができ、リテラルは17です。したがって、小数点以下第2位のリテラルに最も近いdouble
値は255.0
です。
コードの2行目では、Eclipseは実際に警告を発行します。
同一の式の比較
なぜなら、これらはまったく同じdouble
値の2つのリテラルにすぎないという事実を認識しているのは、すでにcompilerだからです。
Doubleは、数値の64ビットバイナリ浮動小数点表現です。 2進浮動小数点数は、ほとんどの小数を正確に表すことはできません。 1/2、1/4、1/64 + 1/32などを正確に表すことはできますが、0.9または0.1を正確に表すことはできません。さらに、それらの精度は制限されています。
あなたの場合、254.99999999999999は内部的に255.0とまったく同じ表現をしています。これは、Double.toHexString
メソッドを使用して、2進小数の16進バージョンをチェックすることで確認できます。 254.99999999999999はすでに255.0に等しいため、小数部分を32ビット整数にキャストして切り取ると、255になります。
System.out.println("a: " + Double.toHexString(254.99999999999999d));
System.out.println("b: " + Double.toHexString(255d));
出力
a: 0x1.fep7
b: 0x1.fep7
答えはかなり簡単です。コードに9を1つ増やして記述した10進数は、他のどのdoubleよりも正確に255を表すdoubleに近くなります。したがって、コンパイルで使用されるdoubleは255に正確に等しくなります。9が1つ少ない10進数は、以下に示すdoubleで最適に表されます。これは、他のどのダブルよりもその特定のダブルに近いことを意味します。
このデモをチェックしてください: http://ideone.com/hSqJTJ
これは出力です:
Original double: 254.9999999999999
Cast to int: 254
Exact double: 254.9999999999998863131622783839702606201171875
Original double: 255.0
Cast to int: 255
Exact double: 255
ダブルバイナリ形式は、符号(1)+指数(11)+分数(53)です。 _254.9999999999999
_と_254.99999999999999
_のバイナリ形式は
_0 10000000110 1111110111111111111111111111111111111111111111111100
0 10000000110 1111111000000000000000000000000000000000000000000000
_
Long.toString(dbl.doubleToLongBits(dbl), 2);
として取得できます
整数部分は
_1111110
1111111
_
先頭の1ビットが省略されているため、実際の整数値は
_11111110 - 254
11111111 - 255
_
倍精度から整数へのキャストは、丸めではなく切り捨てによって行われることに注意してください