2013-02-08 13 views
29

Ultimamente ho scritto un progetto in Java e ho notato una caratteristica molto strana con implementazione doppia/doppia. Il doppio tipo in Java ha due 0, cioè 0.0 e -0.0 (zero firmati). La cosa strana è che:Java firmato zero e boxing

0.0 == -0.0 

viene valutato come true, ma:

new Double(0.0).equals(new Double(-0.0)) 

viene valutato come false. Qualcuno conosce la ragione di questo?

+5

Il solito modo per evitare questo è aggiungere '0.0'. Vedi [qui] (http://stackoverflow.com/a/8153449/823393) per ulteriori dettagli. – OldCurmudgeon

risposta

38

E 'tutto spiegato nel the javadoc:

Nota che nella maggior parte dei casi, per due istanze della classe doppie, D1 e D2, il valore della d1.equals (D2) è vero se e solo se

d1.doubleValue() == d2.doubleValue() 

ha anche il valore true. Tuttavia, ci sono due eccezioni:

  • Se D1 e D2 entrambi rappresentano Double.NaN, quindi il metodo equals restituisce true, anche se Double.NaN == Double.NaN ha il valore falso.
  • Se d1 rappresenta +0.0 mentre d2 rappresenta -0.0 o viceversa, il test di uguaglianza ha il valore falso, anche se +0.0 == - 0.0 ha il valore true.

Questa definizione consente alle tabelle hash di funzionare correttamente.


Ora si potrebbe chiedere perché 0.0 == -0.0 è vero. In realtà non sono strettamente identici. Ad esempio:

Double.doubleToRawLongBits(0.0) == Double.doubleToRawLongBits(-0.0); //false 

è falso. Tuttavia, il JLS richiede ("secondo le norme IEEE 754 standard di") che:

positivo zero e zero negativo sono considerati uguali.

quindi 0.0 == -0.0 è vero.

+2

E JLS richiede questo perché l'IEEE 754 lo richiede. – ninjalj

+1

@ninjalj Infatti - Aggiunto questo chiarimento. – assylias

-5

Utilizzando l'istruzione == si stanno confrontando i valori. Con uguali stai confrontando gli oggetti.

2

È importante sottolineare l'utilizzo dello zero firmato nella classe Double. (Non ci sono carichi di programmatori Java esperti).

La risposta breve è che (per definizione) "-0.0 è inferiore a 0,0" in tutte le modalità previste dalla classe doppia (vale a dire, equals(), confrontare(), compareTo(), ecc)

Double consente a tutti i numeri in virgola mobile di essere "totalmente ordinati su una linea numerica". I primitivi si comportano come un utente pensa alle cose (una definizione del mondo reale) ...0d = -0d

I seguenti frammenti illustrano il comportamento ...

final double d1 = 0d, d2 = -0d; 

System.out.println(d1 == d2); //prints ... true 
System.out.println(d1 < d2); //prints ... false 
System.out.println(d2 < d1); //prints ... false 
System.out.println(Double.compare(d1, d2)); //prints ... 1 
System.out.println(Double.compare(d2, d1)); //prints ... -1 

Ci sono altri posti che sono rilevanti e ben spiegano lo sfondo ...

1: Why do floating-point numbers have signed zeros?

2: Why is Java's Double.compare(double, double) implemented the way it is?

E una parola di cautela ...

Se non si sa che, nella classe doppio, "-0.0 è inferiore a 0.0", si potrebbe rimanere intrappolati quando si utilizzano metodi come equals () e compare() e compareTo() da Double in test logici. Ad esempio, guardate ...

final double d3 = -0d; // try this code with d3 = 0d; for comparison 

if (d3 < 0d) {  
    System.out.println("Pay 1 million pounds penalty"); 
} else {   
    System.out.println("Good things happen"); // this line prints 
} 


if (Double.compare(d3, 0d) < 0) { //use Double.compare(d3, -0d) to match the above behaviour 
    System.out.println("Pay 1 million pounds penalty"); // this line prints 
} else {        
    System.out.println("Good things happen"); 
} 

e per uguale si potrebbe provare ... nuovo doppio (D3) .equals (0d) || new Double (d3) .equals (-0d)