2016-07-29 8 views
2

Ich weiß, dass der Vergleich von zwei doubles ist problematisch, wenn sie aus verschiedenen Berechnungen erhalten werden. Aber gilt das auch für den Fall, dass einer von ihnen eine Kopie (in Wert) des anderen ist? Die folgenden Zeilen erläutern das Szenario. Wenn ich ein Problem wie dieses haben,Vergleichen eines Schwimmers und seiner Kopie

double a,b; 
a=randdouble();/*some double value*/ 
b=a; 

Dann

Q1) Ist der Vergleich a==b immer garantiert true bei den C-Compiler zurückzukehren (ich habe gcc 6.1.1)?

Q2) Würde die obige Antwort gleich bleiben, wenn ich die Variablen a und b im Heap-Speicher unter Verwendung von malloc zuweise?

Q3) Wären die obigen Antworten gleich geblieben, wenn ich C-Compiler durch einen JAVA-Compiler (ich verwende Open JDK 1.7.0) mit den notwendigen Syntaxänderungen natürlich ersetzen würde.

Edit 1: Die Zahlen a und b sind != NaN

+0

1) Nein, 2) Ja, 3) Ja –

+0

@EugeneSh. Warum würde "b = a" nicht dazu führen, dass "b == a" wahr ist? Dies ist eine direkte Kopie des Speichers oder eines Registers. –

+0

@JoshSanford Die Frage dreht sich um * Garantie *. –

Antwort

3

Q1: Der Vergleich ist nicht garantiert, aus dem einfachen Grund, um wahr zu bewerten, dass NaN sich ungleich vergleicht. Es könnte auch andere Fälle geben, aber NaN ist ein offensichtliches Gegenbeispiel.

Q2: Es macht keinen Unterschied, wo sich die Variablen im Speicher befinden.

F3: Ich würde erwarten, dass Java sich ähnlich verhält.

Dieser Sonderfall abgesehen, glaube ich die Norm nicht eine solche Garantie nicht geben:

eines ABI Stellen Sie sich vor, wo double Ausdrücke ausgewertet werden, und Werte werden mit 80-Bit-Genauigkeit (Intel 80x87-Stack), aber gespeichert als 64 zurückgegeben Bit IEEE-754 verdoppelt sich. Auch wenn randdouble() als double definiert ist, im Gegensatz zu long double, ist der Rückgabewert möglicherweise genauer als der in a oder b gespeicherte Wert. Abhängig davon, wie der Compiler die verschiedenen Ausdrücke zwischen dem Funktionsaufruf und dem Vergleich a == b optimiert, kann es am Ende den 80 Bit genauen Rückgabewert mit seinem nahen Cousin vergleichen, der durch Umwandlung in 64 Bit und zurück zu 80 Bit erhalten wird. Der Vergleich würde fehlschlagen, wenn die Genauigkeit bei der Konvertierung verloren ging. Ich werde versuchen, eine angemessene Referenz aus dem Standard zu finden, um dies zu unterstützen, aber es scheint plausibel, und wenn auch a oder b lokale Variablen sind oder auf dem Heap gespeichert werden, könnte einen Unterschied in der Reihenfolge der durchgeführten Konvertierungen machen, wäre es immer noch schlecht -sagte, irgendeine Garantie für die eine oder andere Situation zu übernehmen.

+0

Ich mache die ausfallsichere Prüfung auf Vorhandensein von 'NaN'. Ich werde die Frage über das Fehlen von NaN aktualisieren. Können Sie Ihre Antwort entsprechend aktualisieren? – Abhinav

+0

Die Prüfungen, die Sie vornehmen, ändern die Tatsache nicht. –

+0

@EugeneSh. Wie ist das? Kann ein 'PseudoRandom'-Generator ein' NaN' ergeben? – Abhinav

2

Als eine andere Antwort sagte NaN ist immer garantiert anders zu sein. Dies ist eine Definition des IEEE-754-Gleitkomma-Standards. Sowohl C als auch Java verwenden dies für ihre Float- und Doppelbitdarstellungen und behandeln NaN daher als verschieden.

a=Double.NaN; 
b=a; 

if (a==b) // <--- comparison will fail. 

Aber für alle anderen Werte verhält sich der Vergleich entsprechend dem IEEE-754-Bitmuster des Werts. Wenn die Bitdarstellung der beiden Variablen identisch ist, wird dieser Vergleich wahr ergeben.

Also für Ihr Beispiel mit randdouble() wird Ihr Vergleich von a == b immer wahr ergeben, da Sie die Bitdarstellung von a buchstäblich in die Zuweisung von b kopieren (angenommen randdouble() kann niemals NaN zurückgeben).

Das soll gesagt werden ... Sie sollten sich niemals auf exakte Vergleiche von Fließkommawerten im Code verlassen. Es ist sehr selten, dass Ihre Vergleichswerte durch direkte Zuordnung voneinander erhalten werden, wie in unserem trivialen Beispiel hier. Sie werden normalerweise durch einige Berechnungen erreicht. Jede Seite des Vergleichs wird oft durch eine andere Reihe von Berechnungen erreicht. Die Berechnungen ergeben oft leicht unterschiedliche Ergebnisse in den Bitdarstellungen aufgrund der akkumulierten Fehler, die den IEEE-754-Beschränkungen inhärent sind.

Speicherplätze spielen also keine Rolle, da die Bitmuster unabhängig vom Speicherort identisch sind.

Es spielt auch keine Rolle zwischen C oder Java (oder einer anderen Sprache, die IEEE-754 Gleitkommadarstellung verwendet).

+1

Ist garantiert, dass der Zuweisungsoperator die exakte Bitkopie liefert? Ist sichergestellt, dass die Vergleichsoperation immer genau dann wahr ist, wenn es sich um exakte Bitkopien handelt (mit der NaN-Ausnahme)? Ich denke nicht, aber ich suche nach Referenzen. –

+0

@EugeneSh. Ich denke, das ist der Kern meines Dilemmas. Ist der Zuweisungsoperator eine exakte Bitkopie? – Abhinav

+0

Ich denke du solltest dich nicht darauf verlassen. Wenn Sie die exakte Kopie eines Objekts wirklich kopieren und bitweise vergleichen möchten, verwenden Sie 'memcpy' und' memcmp'. Ich könnte hier aber falsch liegen, da ich keine gute Referenz finde. –

Verwandte Themen