web-dev-qa-db-ja.com

Double.intValue()はどのように機能しますか?

このコード

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です..なぜですか?

30
Artem Ruchkov

ダブルの正確な値を知るには、BigDecimalを使用できます。

System.out.println(new BigDecimal(254.9999999999999));
System.out.println(new BigDecimal(254.99999999999999));

プリント:

254.9999999999998863131622783839702606201171875
255

したがって、これは単に倍精度(の制限)によるものです...

30
assylias
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だからです。

13
Marko Topolnik

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
4
Erwin Bolwidt

答えはかなり簡単です。コードに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
3

ダブルバイナリ形式は、符号(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
_

倍精度から整数へのキャストは、丸めではなく切り捨てによって行われることに注意してください

3