Ich habe einen Algorithmus, der floats
oder doubles
benutzt, um einige Berechnungen durchzuführen.
Beispiel:
%Vor% Jetzt mache ich mir Sorgen, dass (b - a)
gleich null sein könnte. Wenn es nahe Null, aber nicht Null ist, spielt es keine Rolle, da result
außerhalb des Bereichs liegt, um nützlich zu sein, und ich stelle bereits fest, dass ( (b - a)
gegen Null geht, result
gegen +/- inf , die nicht im Bereich 0
- small_number
...)
Aber wenn das Ergebnis von (b - a)
genau Null ist, erwarte ich, dass etwas plattformabhängiges passieren wird, weil es durch Null geteilt wird. Ich könnte die if
-Anweisung zu:
aber ich weiß nicht, ob (b-a) == 0.0
immer Gleichheit mit Null erkennt. Ich habe gesehen, dass es mehrere Darstellungen für die exakte Null im Fließkomma gibt? Wie können Sie für alle testen, ohne einige Epsilon-Prüfung zu machen, die ich nicht brauche (ein kleines Epsilon wird in meinem Algorithmus ignoriert werden)?
Was ist die Plattform unabhängige Überprüfung?
BEARBEITEN:
Nicht sicher, ob es den Leuten klar genug war. Grundsätzlich möchte ich wissen, wie man einen Ausdruck wie folgt findet:
%Vor%führt zu einer Gleitkommaausnahme, einer CPU-Ausnahme, einem Signal vom Betriebssystem oder etwas anderem .... ohne tatsächlich die Operation auszuführen und zu sehen, ob es "werfen" wird ... weil ein "Wurf" erkannt wird dieser Art scheint kompliziert und plattformspezifisch zu sein.
Ist ( (denominator==0.0) || (denominator==-0.0) ) ? "Will 'throw'" : "Won't 'throw'";
genug?
Es hängt davon ab, wie b
und a
ihre Werte erhalten haben. Null hat eine exakte Darstellung im Fließkommaformat, aber das größere Problem wäre fast, aber nicht ganz Null. Es wäre immer sicher zu überprüfen:
Dabei ist 0,00000001, welcher Wert auch immer sinnvoll ist.
Ich denke, Sie können fpclassify(-0.0) == FP_ZERO
verwenden. Aber das ist nur nützlich, wenn Sie überprüfen möchten, ob jemand eine Null in eine Variable vom Typ float gesetzt hat. Wie viele bereits sagten, wenn Sie das Ergebnis der Berechnung überprüfen möchten, können Sie aufgrund der Art der Darstellung Werte nahe Null erhalten.
Ich glaube, dass (b-a)==0
genau dann wahr ist, wenn die c/(b-a)
fehlschlagen würde, weil (b-a)
null ist. Die float maths ist schwierig, aber die Frage ist meiner Meinung nach übertrieben. Ich glaube auch, dass (b-a)==0
gleich b!=a
ist.
Das Unterscheiden von positivem und negativem 0 ist ebenfalls nicht notwendig. Siehe z.B. Hier Hat Float eine negative Null? (-0f)
Für epsilon gibt es eine Standardschablonendefinition std :: numeric_limits :: epsilon (). Ich denke, dass die Überprüfung der Differenz größer als std :: numeric_limits :: epsilon () sicher genug ist, um gegen Division durch Null zu schützen. Keine Plattformabhängigkeit hier, denke ich.
Kurz gesagt, können wir wissen, dass eine Fließkommazahl genau dann NULL ist, wenn wir wissen, dass sie das Format darstellt.
In der Praxis vergleichen wir x
mit einer kleinen Zahl. Und wenn x
kleiner als diese Zahl ist, denken wir, dass x
genauso funktional ist wie ZERO (aber die meiste Zeit ist unsere kleine Zahl immer noch größer als Null). Diese Methode ist sehr einfach, effizient und plattformübergreifend.
Tatsächlich wurden die float
und double
in einem speziellen Format dargestellt, und das häufigste ist IEEE 754 in der aktuellen Hardware, die die Zahl in Vorzeichen-, Exponenten- und Mantissenbits (Signifikand) aufteilte.
Wenn wir also überprüfen wollen, ob eine Gleitkommazahl ZERO genau ist, können wir prüfen, ob sowohl der Exponent als auch die Mantisse NULL ist, siehe hier .
In IEEE 754 binären Fließkommazahlen werden Nullwerte dargestellt durch den voreingenommenen Exponenten und den Signifikanten, die beide Null sind. Negative Null hat das Vorzeichen-Bit auf eins gesetzt.
Nimm float
zum Beispiel, wir können einen einfachen Code schreiben, um das Exponenten- und Mantissen-Bit zu extrahieren und es dann zu überprüfen.
Testergebnisse:
# ist Null von 0,000000 - & gt; 1
# ist Null von -0,000000 - & gt; 1
# ist Null von 1.200000 - & gt; 0
Weitere Beispiele:
Lassen Sie uns prüfen, wann die float
mit Code wirklich NULL wird.
UPDATE (2016-01-04)
Ich habe einige Antworten auf diese Antwort erhalten, und ich habe mich gefragt, ob ich sie einfach löschen sollte. Es scheint der Konsens ( Ссылка ) zu sein, dass das Löschen von Antworten nur in gemacht werden sollte Extremfälle.
Also, meine Antwort ist falsch. Aber ich denke, ich verlasse es, weil es für ein interessantes "Think out of the box" Gedankenexperiment sorgt.
================
Bingo,
Sie sagen, Sie möchten wissen, ob b-a == 0 ist.
Eine andere Möglichkeit, dies zu betrachten, ist festzustellen, ob a == b. Wenn a gleich b ist, dann wird b-a gleich 0 sein.
Eine weitere interessante Idee, die ich gefunden habe:
Im Wesentlichen nehmen Sie die Gleitkommavariablen, die Sie haben, und weisen den Compiler an, sie (Bit für Bit) als Ganzzahlen mit Vorzeichen neu zu interpretieren, wie im Folgenden:
%Vor%Dann vergleichen Sie ganze Zahlen und keine Fließkommawerte. Vielleicht hilft das? Vielleicht nicht. Viel Glück!
Tags und Links c++ floating-point