2012-01-18 8 views
16

dlaczego Double.parseDouble powoduje 9999999999999999 do 10000000000000000? Dla przykładu:dlaczego Double.parse Double zarabia 9999999999999999 na 10000000000000000?

Double d =Double.parseDouble("9999999999999999"); 
String b= new DecimalFormat("#.##").format(d); 
System.out.println(b); 

drukuje

10000000000000000 

zamiast tego musi pokazać 9999999999999999 lub 9999999999999999.00

wszelkiego rodzaju pomoc jest mile widziana.

+11

Arytmetyka zmiennoprzecinkowa --- największa tajemnica informatyki od 1985 roku – subsub

Odpowiedz

12

double ma tylko 15/16 cyfr dokładności, a kiedy dać mu numer nie może reprezentować (który jest przez większość czasu, nawet 0,1 jest niepoprawne) zajmuje najbliższy reprezentowalny numer.

Jeśli chcesz reprezentować dokładnie 9999999999999999, musisz użyć BigDecimal.

BigDecimal bd = new BigDecimal("9999999999999999"); 
System.out.println(new DecimalFormat("#.##").format(bd)); 

drukuje

9999999999999999 

Bardzo niewiele rzeczywistych problemów trzeba tę dokładność, ponieważ nie można czegoś zmierzyć to dokładnie tak. tj. do błędu 1 części na kwintillion.


można znaleźć największą reprezentowalna całkowitą z

// search all the powers of 2 until (x + 1) - x != 1 
for (long l = 1; l > 0; l <<= 1) { 
    double d0 = l; 
    double d1 = l + 1; 
    if (d1 - d0 != 1) { 
     System.out.println("Cannot represent " + (l + 1) + " was " + d1); 
     break; 
    } 
} 

wydruków

Cannot represent 9007199254740993 was 9.007199254740992E15 

Największy reprezentowalna całkowita jest 9007199254740992 ile potrzebuje jeden mniej trochę (jak sama nawet)

+1

O wiele bardziej przydatne jest używanie arytmetyki binarnej, gdy myślimy o normalnym podwojeniu IEEE, niż o przybliżeniu dziesiętnym. –

+0

9007199254740992 = 20000000000000 (hex) = 100000000000000000000000000000000000000000000000000000 (bin) –

+0

@DonalFellows To prawda, dlatego biorę pod uwagę tylko moc 2. –

15

Numer 9999999999999999 znajduje się nieco powyżej granicy dokładności zmiennoprzecinkowej podwójnej precyzji. Innymi słowy, 53-bitowa mantysa nie jest w stanie pomieścić 9999999999999999.

Rezultatem jest zaokrąglenie do najbliższej wartości podwójnej precyzji - czyli 10000000000000000.

9999999999999999 = 0x2386f26fc0ffff // 54 significant bits needed 
10000000000000000 = 0x2386f26fc10000 // 38 significant bits needed 
+0

+1: Dokładnie to. Potrzeba _54_ bitów do przedstawienia bez znaku 9999999999999999, a największa wartość, która będzie dokładnie pasować do standardowego podwójnego, to 9007199254740991. –

+0

@DonalFellows Czy nie byłaby to liczba parzysta?Jeśli 9007199254740991 może być reprezentowany 9007199254740992 również musi być reprezentowany. –

+0

@Peter: 0x1fffffffffffff jest nieparzystą liczbą, która wymaga co najmniej 53 bitów do przedstawienia. Numer jeden większy wymaga 54 bitów (lub wykładnika). Zgadnij, co to jest wartość dziesiętna? :-) –

5

9999999999999999 wymaga 54 bitów mantysie w celu uzyskania dokładnie przedstawiony i double ma tylko 52. W związku z tym liczba zaokrągloną do najbliższej liczby że mogą być reprezentowane przy użyciu 52-bitowego podstawa. Ta liczba to 10000000000000000.

Powodem, dla którego 10000000000000000 wymaga mniejszej liczby bitów, jest to, że jego reprezentacja binarna kończy się wieloma zerami, a te zera mogą być reprezentowane przez zwiększenie wykładnika (binarnego).

Szczegółowe wyjaśnienie podobnego problemu, zobacz Why is (long)9223372036854665200d giving me 9223372036854665216?

Powiązane problemy