2014-10-08 12 views
5

Nel mio vecchia conoscenza: quando vogliamo verificare se un letto matrimoniale o flottante è pari 0.0,
abbiamo non dovrebbe scrivere in questo modo:
In corrente C++ e Java, doppio tipo e tipo float: if (x == 0.0) è corretto?

double x = 0.0; 
if (x == 0.0) System.out.println("yes"); 
else System.out.println("no"); 

Ma qualche minuto fa, ho provato ancora una volta, sotto Java (1.7) e C++ (Apple LLVM versione 6.0), non c'è nessun problema a scrivere in quel modo! Ho provato sia il tipo "double" che il tipo "float" in Java e C++, rispettivamente.

La mia domanda:

  • Mi sono perso qualcosa, o siamo davvero in grado di controllare il doppio o galleggiare come che sotto Java attuale e C++.
  • Se possiamo, se possiamo farlo con la versione precedente di Java e C++?


Conclusione (sulla base di tutte aiuta):
Noi non dovrebbe uso "galleggiare == float o doppi == doppi" per verificare se due galleggianti o due doppie sono uguali ( se vogliamo ottenere la risposta giusta), i motivi sono in tutte le risposte e i commenti sotto.


Edition (prima volta):
Grazie mille per tutto l'aiuto!
Ma un minuto fa, cerco solo di questi sotto Java (1.7), tutto spettacolo " ",
sembra che davvero in grado di farlo in corrente Java!

float x = 0.0f; 
if (x == 0) System.out.println("yes"); 
else System.out.println("no"); 

float y = 100.0f - 50.0f*2.0f + 45.0f*3 - 135.0f; 
if (y == 0.0f) System.out.println("yes"); 
else System.out.println("no"); 

if (100.0f - 50.0f*2.0f + 45.0f*3 - 135.0f == 0.0f) System.out.println("yes"); 
else System.out.println("no"); 


edizione (seconda volta):
Ma ho provato questo, Java mostra anche " ", (in Java (1.7)).
Io provo a eliminare "pre-compute" del compilatore e dividere il calcolo in diversi passaggi.

float a = 100.0f; 
float b = 50.0f; 
float c = 2.0f; 
float bc = b * c; 
System.out.println("b*c = " + bc); 

float d = 45.0f; 
float e = 3.0f; 
float de = d * e; 
System.out.println("d*e = " + de); 

float f = 135.0f; 

float g = a - bc + de - f; 
float h = 0.0f; 
if (g == h) System.out.println("yes"); 
else System.out.println("no"); 


edizione (terza volta):
Grazie per @ di DiegoBasch controesempio (per float == float):
Questa volta Java (1.7) mostra " no".

float m = 0.37f - 0.36f; 
float n = 0.01f; 
if (m - n == 0.0f) System.out.println("yes"); 
else System.out.println("no"); 
+13

'x' è esattamente' 0', quindi è OK. Il problema è quando 'x' è il risultato di una sequenza di operazioni che matematicamente produrrebbe' 0', ma non danno come risultato '0.0' per ragioni numeriche. – juanchopanza

+3

Per approfondire ciò che @juanchopanza ha detto, nel tuo caso valuterà il vero, ma non puoi garantire che '100.0 - 50.0 * 2.0 == 0.0' anche se matematicamente dovrebbe. – CoryKramer

+3

I punti mobili sono spesso descritti come valori "approssimativi", il che è fuorviante. Un numero in virgola mobile ha un valore esatto, è solo che questo valore potrebbe non essere esattamente quello che ti aspetti a causa della precisione limitata. Pertanto, se lo stai confrontando con un valore atteso, dovresti chiedere "sono esattamente uguali", ma piuttosto "sono abbastanza vicini". '0.0' non è diverso da' 1.3' o '3.14159' in questo senso. – yshavit

risposta

6

Il codice è legale. Il problema è che quando si eseguono calcoli che coinvolgono numeri in virgola mobile, ci saranno errori di arrotondamento e quindi in molti casi il controllo per esattamente 0 (o il controllo di due numeri per l'uguaglianza) non funzionerà.

Questo codice va bene in qualsiasi lingua poiché non l'ha fatto nulla che possa causare l'arrotondamento:

double x = 0.0; 
if (x == 0.0) System.out.println("yes"); 
else System.out.println("no"); 

Questo codice non può andare bene, però:

double a1 = ...something...; 
double a2 = ...something...; 
double a3 = a1/a2; 
double a4 = a3 * a2; 
double a5 = a4 - a1; 
if (a5 == 0.0) ... 

Anche se matematicamente a5 dovrebbe essere 0, in pratica l'operazione == potrebbe restituire false a causa dell'arrotondamento.

Ciò richiede una comprensione di come viene gestito il punto mobile in un computer; non ha nulla a che fare con qualsiasi lingua o versione di una lingua. Un riferimento è What Every Computer Scientist Should Know About Floating-Point.

+4

[Questo sito] (http://floating-point-gui.de/) è spesso citato come "il documento di Goldberg in forma digeribile". – Angew

+0

Ciao @ajb, grazie mille per il tuo aiuto, ma l'ho appena provato con alcuni calcoli in Java (1.7) funziona ... vedi la mia edizione, sembra che possiamo davvero farlo sotto Java ora. – Zhaonan

+0

@Zhaonan vedi il mio commento in risposta alla tua modifica. '==' funzionerà con numeri _some_, e questo è sempre stato il caso. Non funzionerà in tutti i casi. Non ha nulla a che fare con la versione di Java. – ajb

2

Per completare la risposta di ajb, ecco un esempio di errore numerico. Non hai bisogno di molti calcoli perché ciò avvenga.

double a = 0.37 - 0.36; // 0.010000000000000009 
    double b = 0.01; 
    System.out.println (a - b == 0.0); // false 
+0

Ciao @Diego Basch, grazie mille per il tuo controesempio, ora credo che "float == float" non funzionerà in tutti i casi. – Zhaonan

Problemi correlati