2015-08-14 24 views
6

Perché Java è incoerente nel confronto tra -0.0 e +0.0? Qual è il metodo standard Java per confrontare i numeri con l'account -0/+ 0?Java: confronto di zeri positivi e negativi

ho incontrato questo particolare Bugaboo:

public class ZeroCompare { 
    public static void main(String[] args) { 
     if (0.0 == -0.0) { 
      System.out.println("== --> same"); 
     } else { 
      System.out.println("== --> different"); 
     } 

     if (new Double(0.0).equals(-0.0)) { 
      System.out.println("equals --> same"); 
     } else { 
      System.out.println("equals --> different"); 
     } 
    } 
} 

Esso stampa il seguente:

== --> same 
equals --> different 

Cosa non mi piace con forza il fatto che come si confrontano questi due valori influisce sul risultato e mi piacerebbe per una spiegazione.

+0

primi di uguale all'interno letterali (-0.0) non è forse virgola mobile in doppia. e in secondo luogo il metodo equals confronta gli oggetti e per letterali diversi ci sono diversi oggetti wrapper. –

+1

@amitmahajan È un doppio. Richiederebbe un 'f' o' F' alla fine per essere un letterale float. – Kayaman

+0

A proposito, i numeri in virgola mobile non vengono mai confrontati per l'uguaglianza esatta. Richiedono un piccolo valore delta per vedere se due numeri sono abbastanza vicini da essere considerati uguali (anche se in questo caso particolare si tratta di un problema minore). – Kayaman

risposta

10

Questo comportamento è actually documented:

Se d1 rappresenta +0.0 mentre d2 rappresenta -0.0, o viceversa, la prova pari ha il valore falso, anche se +0.0 == - 0.0 ha il valore vero . Questa definizione consente alle tabelle hash di funzionare correttamente.

+0

Nice caveat in the Javadoc ... – Kayaman

+0

Grazie per il link. Quando l'ho cercato su google, inizialmente avevo sperato che il documento java sarebbe stato tirato su. Ma a quanto pare, Google trova lo StackOverflow molto più popolare. – Curds

+1

Non so se sono d'accordo con la determinazione di Java che questo "consente alle tabelle hash di funzionare correttamente" Immagina di avere valori in virgola mobile (32 o 64 bit) che sto utilizzando come chiave in una mappa hash (strano, lo so. È un esempio.) Supponiamo che il mio codice funzioni con i float, ma hash su Floats. Grazie alla funzione di autoboxing, posso indicizzare direttamente con il float. Fuori dalla mappa hash, 0.0 e -0.0 confrontava lo stesso, ma creava due voci diverse nella mappa hash. Python va dall'altra parte; poiché 0.0 e -0.0 sono considerati "uguali", hanno lo stesso hash. Penso di preferirlo. – Curds

1

Java Language Specification: Numerical Comparison Operators <, <=, >, and >=

zero positivo e zero negativo sono considerati uguali.

Double.valueOf (+0.0) e Double.valueOf (-0.0) hanno rappresentazione di bit diversi. Double.equals confronta la rappresentazione dei bit.

Inoltre è possibile utilizzare Double.compare

+0

Sono sorpreso che la rappresentazione a doppio bit di +/- 0.0 sia diversa dalla rappresentazione primitiva. Ho sempre pensato che fosse semplicemente un object wrapper in modo da poter spingere la primitiva in collezioni. Detto questo, anche se la rappresentazione bit del valore sottostante era identica alla primitiva (che presumo sia il caso), il metodo "equals" non è vincolato in alcun modo forma o forma per utilizzare l'operatore == per determinare l'uguaglianza. Questo è un po 'il suo punto. – Curds

+0

La rappresentazione è diversa anche per il tipo primitivo, ma la specifica di Java lang dice che gli operatori (><...) non usano il confronto bit-bit. – sibnick