2012-11-24 4 views
5

den folgenden Java-Code vor:ein Doppel aus einem String parsen, die einen Wert von mehr als Double.MaxValue halten

String toParse = "1.7976931348623157E308"; //max value of a double in java   
double parsed = Double.parseDouble(toParse); 
System.out.println(parsed); 

Für den genannten Wert von 1.7976931348623157E308 alles macht Sinn, und man bekommt die richtige Ausgabe.

Jetzt, wenn man versucht, 1.7976931348623158E308 (letzte Ziffer vor E inkrementiert) zu analysieren, erhalten Sie immer noch den Maximalwert in die Konsole gedruckt!
Nur nach dem Versuch zu analysieren 1.7976931348623159E308 (wieder die letzte Ziffer wurde inkrementiert) und größer bekommt man Infinity.
Gleiches Verhalten für die entsprechenden negativen Werte.

Warum wird ... 8E308 geparst zu ... 7E308 und nicht Infinity?

+1

Hat das irgendeine Relevanz für irgendeine Anwendung? – AlexWien

+1

Ich vermute, dass Sie Spaß mit Rand Fällen haben. Hast du den Quellcode angeschaut? –

+0

@AlexWien ist gerade durch "Unfall" darauf gestoßen, jetzt bin ich neugierig –

Antwort

9

Die SE-7-Version der parseDouble Dokumentation bezieht sich auf die valueOf Dokumentation, die sagt:

Beachten Sie, dass die rundlich-nächste Regel auch Über- und Unterlauf Verhalten impliziert; Wenn der genaue Wert von s groß genug ist (größer als oder gleich (MAX_VALUE + ulp (MAX_VALUE)/2), führt das Runden auf das Doppelte zu einer Unendlichkeit, und wenn der genaue Wert von s klein genug ist (weniger als oder gleich/2) MIN_VALUE, in einem Null führt zu schweben Rundung.

mit der Aussage Dies steht im Einklang, daß die Rundungsdoppel wird durch die übliche Rund zu-nearest-Regel von IEEE 754 einzugeben Floating -Punktarithmetik

Sie müssen sich die Umrechnung vorstellen, indem Sie zuerst die nächste Gleitkommazahl ohne Berücksichtigung der Exponentenbegrenzung berechnen und dann prüfen, ob der Exponent passt.Doppel.MAX_WERT ist die Nummer unter dieser Regel, die einigen Zahlen am nächsten kommt Das sind streng größer als es.

Um dies zu bestätigen normalen Rundungsverhalten ist, sollten Sie das folgende Programm:

public class Test { 
     public static void main(String[] args) { 
     double ulp = Math.ulp(Double.MAX_VALUE); 
     System.out.println(ulp); 
     System.out.println(Double.MAX_VALUE); 
     System.out.println(Double.MAX_VALUE+ulp/2.0000000001); 
     System.out.println(Double.MAX_VALUE+ulp/2); 
     } 
    } 

Es gibt:

1.9958403095347198E292 
1.7976931348623157E308 
1.7976931348623157E308 
Infinity 

etwas hinzufügen noch etwas weniger als eine halbe ULP Double.MAX_VALUE nicht ändert es. Das Hinzufügen einer halben ul überläuft die Unendlichkeit.

+0

+1 für den Beispiel-Code, das war der Teil, der meinen Kopf um mich legte! Danke, Patricia –

Verwandte Themen