2012-11-24 4 views
5

consideri il seguente codice Java:Parsing un letto da una stringa che contiene un valore maggiore di Double.MaxValue

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

Per il valore indicato di 1.7976931348623157E308 tutto senso e si ha l'uscita corretta.

Ora, se si tenta di analizzare 1.7976931348623158E308 (l'ultima cifra prima di E incrementata) si ottiene ancora il valore massimo stampato nella console!
Solo dopo aver provato a analizzare 1.7976931348623159E308 (anche in questo caso l'ultima cifra è stata incrementata) e una maggiore diventa Infinity.
Stesso comportamento per i corrispondenti valori negativi.

Perché ... 8E308 è stato analizzato a ... 7E308 e non Infinity?

+1

Ha rilevanza per qualsiasi applicazione? – AlexWien

+1

Immagino che ti stia divertendo con i casi limite. Hai guardato il codice sorgente? –

+0

@AlexWien si è appena imbattuto in questo "incidente", ora sono curioso –

risposta

9

La versione SE 7 della documentazione parseDouble si riferisce alla documentazione valueOf che dice:

Si noti che il round-a-più vicino regola implica anche troppo pieno e il comportamento underflow; se il valore esatto di s è abbastanza grande in grandezza (maggiore o uguale a (MAX_VALUE + ulp (MAX_VALUE)/2), l'arrotondamento a doppio avrà come risultato un infinito e se il valore esatto di s è abbastanza piccolo in magnitudine (meno o uguale a MIN_VALUE/2), arrotondamento a galleggiare si tradurrà in uno zero.

Ciò è coerente con l'affermazione che l'arrotondamento di tipo double è di regola solita round-a-nearest di IEEE 754 galleggiante aritmetica -punto.

Devi immaginare la conversione svolto dal primo calcolo del numero punto più vicino floating ignorando la limitazione esponente, e quindi verificare se l'esponente adatta. Double.MAX_VALUE è il numero più vicino in che regola alcuni numeri quella sono strettamente più grandi di quello

A conferma di ciò è normale comportamento di arrotondamento, si consideri il seguente programma:

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); 
     } 
    } 

Produce:

1.9958403095347198E292 
1.7976931348623157E308 
1.7976931348623157E308 
Infinity 

Aggiunta di qualcosa di ancora un po 'meno della metà di un ULP a Double.MAX_VALUE non cambia esso. L'aggiunta di mezzo ulp trabocca all'infinito.

+0

+1 per il codice di esempio, questa era la parte che mi avvolgeva la testa! grazie, patricia –