float / doppelte Gleichheit mit exakter Null

8

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 ...)

liegt

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:

ändern %Vor%

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?

    
Bingo 03.03.2012, 00:57
quelle

8 Antworten

9

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:

%Vor%

Dabei ist 0,00000001, welcher Wert auch immer sinnvoll ist.

    
wallyk 03.03.2012 01:03
quelle
4

So geht's: Anstatt nach (result < small_number) zu suchen, suchen Sie nach

%Vor%

Dann verschwinden alle deine Probleme! Die Berechnung von c/(b-a) wird niemals überlaufen, wenn dieser Test bestanden wird.

    
TonyK 20.05.2013 21:03
quelle
2

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.

    
ony 10.09.2015 21:04
quelle
0

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)

    
David L. 20.05.2013 15:22
quelle
0

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.

    
mcjoan 13.09.2013 17:22
quelle
0

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.

%Vor%

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.

%Vor%     
Patric 17.12.2015 03:13
quelle
0

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!

    
Aaron Johnson 03.03.2012 01:08
quelle
-1

Sie könnten es versuchen

%Vor%     
Mark 03.03.2012 01:06
quelle

Tags und Links