Wann ist es in der Programmierung normalerweise sinnvoll, die Gleichheit zweier Gleitkommazahlen zu testen?
dh
a == b
wo beide a & b schwimmt.
Mein naiver Eindruck ist, dass man den Unterschied immer gegen ein Toleranz-Epsilon testen würde.
Liege ich falsch? Kann es in bestimmten Kontexten sinnvoll sein, die Gleichheit von Floats zu testen?
Irgendwelche Beispiele aus der Wildnis? dh von echten Codebasen oder Anwendungen da draußen auf Git usw.
PS. Ich gehe implizit davon aus, dass die Verwendung des Gleichheitsoperators für Floats in einigen Kontexten tatsächlich sinnvoll ist . Warum sollten die meisten Programmiersprachen dies sonst zulassen?
floating-point
neugierig_katze
quelle
quelle
Antworten:
Eine nicht naive Implementierung dieser Idee sollte wahrscheinlich den Gleichheitsvergleichsoperator nutzen, um die wichtigen Sonderfälle zu behandeln, die der IEEE 754- Standard in Betracht zieht (Unendlichkeiten, denormalisierte Zahlen ...).
Werfen Sie einen Blick auf Wie soll ich einen Gleitkomma-Vergleich durchführen? ::
Manchmal gibt es wirklich eine Antwort, die richtig ist und Sie wollen exakte Gleichheit. Das Testen der Richtigkeit einer Implementierung ist ein gutes Beispiel (dh es gibt nur vier Milliarden Floats - also testen Sie sie alle! ).
quelle
Ein naheliegendes Beispiel, bei dem
==
es in Ordnung ist, ist, wanna
undb
mit derselben Nummera=c; b=c
, z. B. um zu überprüfen, oba
undb
auf dieselbe Weise initialisiert wurden.|a-b| < epsilon
Würde natürlich auch hier funktionieren. Das einzige Problem ist, wie klein istepsilon
?Außerdem
a == b
würde in eine Anweisung kompiliert, während|a-b| < epsilon
einige dauern würde.quelle
for x in [0..n] step w: for y in [0..n] step w: add_tile(x, y)
. In diesem Fall können Sie auft1.x == t2.x
sichere Weise testen, ob sich die beiden Kacheln in einer Ebene befinden. Sie brauchen nur,|a-b|<epsilon
wenna
undb
Ergebnisse verschiedener Berechnungen sind, die den gleichen Wert erhalten sollten. Sehr oft wird jedoch eine Berechnung in zwei Variablen gespeichert oder Variablen mit Konstanten überschrieben.Ein extremes Beispiel: IBM war das erste Unternehmen, das Prozessoren mit einer fusionierten Multiplikationsaddition aufbaute. Mit dieser Anweisung erstellten sie eine sehr schnelle Methode zur Berechnung von Quadratwurzeln gemäß dem IEEE-754-Standard. Diese Methode schlägt für einen einzelnen Eingabewert 1 ≤ x <4 fehl: Wenn x die größte Zahl ist, die als Gleitkommazahl kleiner als 4 dargestellt werden kann, wird das Ergebnis falsch gerundet.
Irgendwo in ihrer Implementierung prüfen sie also, ob x diesem einen bestimmten Wert entspricht. Sie wollen diesen Wert erkennen und keine anderen.
quelle
Es gibt keine einzigartigen Rezepte. In diesem Artikel finden Sie eine ausführliche Beschreibung, in der Sie eine vollständige Antwort mit technischen Informationen und Code finden.
Zusammenfassend gibt es hauptsächlich 3 Fälle:
Ihre Idee, einen Vergleich mit einer Toleranz durchzuführen, ist in einigen Fällen gut, aber es gibt auch eine Technik, die auf der Einheit an letzter Stelle ( ULP ) basiert und im Artikel beschrieben wird
Wie oben gibt es Situationen, in denen Sie es verwenden können, aber seien Sie gewarnt. Zum Beispiel hat der gcc-Compiler eine Warnung:
Aktualisieren
Ich füge einige Überlegungen über diesem Argument hinzu, auch sie sind nicht eng mit dem Fall verbunden
a == b
.Gleichheit mit Ausdruck
Betrachtet man den Fall:
a b c
In diesem Fall ist die Verwendung
==
also heikler.Portierung in verschiedenen Umgebungen
Wenn wir einen Code in verschiedenen Umgebungen (verschiedenen Maschinen) portieren, können wir unterschiedliche Ergebnisse erzielen (versuchen Sie beispielsweise, an einen Komponententest zu denken). Auch in dem Fall ist die Verwendung von
==
empfindlich.quelle
Ihr "naiver Eindruck" ist kein "naiver Eindruck" - er ist das Ergebnis des Lesens über Gleitkomma-Arithmetik und nur des halben Verstehens. Der "naive Eindruck" wäre der offensichtliche Eindruck, dass man fragt, ob a und b gleich sind, um herauszufinden, ob sie gleich sind.
Es gibt viele Situationen, in denen Sie nur wissen müssen, ob zwei Gleitkommazahlen gleich sind oder nicht. Es gibt viele Situationen, in denen Sie wissen, dass entweder keine Rundungsfehler oder keine Abweichungen aufgrund von Rundungsfehlern vorliegen. Wie das Konvertieren von Dezimalzahlen in Gleitkommazahlen, was bei jeder vernünftigen Implementierung deterministisch ist.
Hier ist eine gute: Jemand hat behauptet, dass für zwei beliebige Gleitkommazahlen a, b das Ergebnis von (b + a + b) und (b + b + a) dasselbe ist und Sie diese Behauptung testen möchten. Versuchen Sie dies, ohne zwei Gleitkommazahlen auf Gleichheit zu vergleichen.
Hier ist eine bessere: Versuchen Sie, eine Reihe von Gleitkommazahlen zu erstellen.
quelle
Siehe diese Frage: /cs/19013/is-transitivity-required-for-a-sorting-algorithm?rq=1
Es erklärt sehr gut, wie ein Gleitkomma-Vergleich mit einigen Epsilons zu einem vollständigen und vollständigen Ausfall des Quicksort-Algorithmus führen kann.
quelle