2016-12-06 4 views
1

Es gibt eine Menge von Dokumenten und Diskussionen über den Vergleich der Float-Zahl. Aber für mich ist es nicht klar, kann man immer garantieren, dass der direkte Zahlenvergleich auf allen Compilern und Plattformen funktioniert?Double/Float-Vergleich mit genauen Werten

double x = 1.; 
if (1. == x) 
{ 
    //do something 
} 

Werden wir immer den if Block eingeben?

Edited:

Und was Vergleich hier korrekt ist (funktioniert immer)? Dieses ?:

double x = 1.; 
if (std::abs(1. - x) < std::numeric_limits<double>::epsilon()) 
{ 
    //do something 
} 
+4

Einige Fließkommawerte, wie zum Beispiel '1.0', können genau im IEEE Fließkommaformat dargestellt werden (welches das meist verwendete Format ist). So wird Ihr Vergleich in genau dem Code funktionieren, den Sie zeigen. Versuchen Sie jedoch, einige Operationen an 'x' durchzuführen, die * als * 1.0 'zurücklassen und den Vergleich wiederholen sollten. Dies wird höchstwahrscheinlich nicht funktionieren. –

+0

Klingt so, als ob Sie das lesen sollten: https://docs.oracle.com/cd/E19957-01/806-3568/ncg_goldberg.html –

+0

Um den zweiten Teil Ihrer Frage zu adressieren, no, 'std :: numeric_limits : : epsilon() 'soll nicht so verwendet werden. 'std :: numeric_limits :: epsilon()' ist ein Maß für die Genauigkeit des Formats, es ist kein Maß für die Genauigkeit der vorangegangenen Berechnungen. Wenn vorausgehende Berechnungen einen absoluten Fehler von 0,125 verursacht haben und Sie einen Test wünschen, der ohne falsche Negative erkennt, wenn die mathematische Berechnung 1,0 ergeben hätte, verwenden Sie "std :: abs (1. - x) <= 0,125". Es gibt keinen magischen Wert, der unabhängig vom Kontext in allen Fällen auf der RHS verwendet werden kann. –

Antwort

0

Wenn Sie zwei genau Gleitkommawerte, Sie müssen nicht befürchten, dass sie im Vergleich zu Ihren Erwartungen entgegen arbeiten. Das Problem ist, woher wissen Sie, dass Ihre Werte genau sind?

Für das mitgelieferte Beispiel können Sie ziemlich sicher sein, dass x == 1.0 zu true bewerten werde - ich persönlich würde nicht in Betracht ziehen, irgendeine Plattform zu unterstützen, die diesen Test nicht bestehen würde. Es ist jedoch möglich, Ihr Beispiel schrittweise zu verfeinern, ohne sicher sagen zu können, an welcher Stelle Sie aufhören sollten, sich auf das Ergebnis des Vergleichs zu verlassen.

1

Ja, direkter Vergleich wie dieser - ohne Eingriffe - wird immer funktionieren. Das Bitmuster, das für ein Fließkomma-Literal gespeichert wird, ist das am nächsten vom Fließkomma-System darstellbare Bitmuster (fast immer IEEE-754). So funktioniert das Testen 1.0 == 1.0 immer, weil das Bitmuster das von 1.0 ist; und 0.3 == 0.3 wird auch immer funktionieren, weil das Bitmuster - obwohl nicht genau 0,3 - ist die nächstgelegene darstellbare Zahl zu 0,3, in beiden Fällen.

Für die Epsilon-Sache, bleiben Sie weg von der Maschine Epsilon, bis Sie tatsächlich wissen, was es darstellt und wofür es ist. Maschine Epsilon ist relativ, nicht absolut; und es zu verwenden, um "nahe genug" zu vergleichen, erfordert ein Verständnis, wie viel Fehler verschiedene Operationen einführen können. Interessanterweise sind die beiden Tests in Ihrem speziellen Fall tatsächlich identisch: Nur genau 1,0 wird den Test bestehen.

Verwandte Themen