2016-07-25 9 views
9

Ich habe eine Nummer, die Nullen sein könnte. Ich dividiere durch diese Zahl, also möchte ich testen, ob es Null ist, um NaNs und Unendlichkeiten zu verhindern. Ist es möglich, dass ich NaNs/Unendlichkeit aufgrund von Rundungsfehlern innerhalb der Division noch erstelle?Kann Division durch Nicht-Null immer noch eine Nan/Unendlichkeit

double x; // might be zero 
double y; 

if(x != 0) return y/x; 

EDIT

Danke für die Antworten. Ich werde dann einige Unterfragen hinzufügen.

1) Angenommen, weder x noch y ist NaN/+ inf oder -inf, würde eine Division mit -inf/+ inf zu mehr CPU-Zyklen oder anderen unerwünschten Verhaltensweisen führen? (Konnte es abstürzen?)

2) Gibt es eine Möglichkeit, die Division von Unendlich zu verhindern? Offsets verwenden und so weiter.

+0

konnten sie unendlich oder sogar nan – EFenix

+2

sein, wenn 'y' ist bereits NaN, dann ist das Ergebnis wird auch NaN sein. –

+2

Das Hinzufügen von weiteren Fragen, nachdem jemand bereits eine Antwort veröffentlicht hat (3 in diesem Fall), ist nicht großartig - es lässt diese Antworten unvollständig erscheinen, obwohl sie nicht waren, als sie geschrieben wurden. –

Antwort

6

Das Teilen einer sehr kleinen Zahl in eine sehr große Zahl oder die Multiplikation zweier sehr großer Zahlen kann eine "Unendlichkeit" ergeben. Die Division einer Unendlichkeit durch eine andere Unendlichkeit ergibt ein NaN. Zum Beispiel ergeben (1E300/1E-300)/(1E300/1E-300) oder (1E300*1E300)/(1E300*1E300) beide NaN.

9

Can Division durch Nicht-Null schaffen noch eine nan/infinity

Ja.

Wenn IEEE-754 dann folgt:

  • Wenn einer der Operanden NaN ist, wird das Ergebnis NaN sein.
  • Wenn sowohl Zähler als auch Denumerator unendlich sind, lautet das Ergebnis NaN.
  • Wenn nur der Zähler unendlich ist, ist das Ergebnis unendlich.
  • Wenn die Division durch kleinen Denumerator (oder großen Zähler) überläuft, kann das Ergebnis je nach aktuellem Rundungsmodus unendlich sein.

Regeln anderer Darstellungen können unterschiedlich sein.


2) ist es eine Möglichkeit, die devision zu verhindern, dass in der Unendlichkeit resultierenden

Diese einen langen Weg gehen sollte, dass bei der Prävention:

#include <cfenv> 
#include <cassert> 
#include <cmath> 
#include <limits> 

// ... 

static_assert(std::numeric_limits<decltype(x)>::is_iec559, "Unknown floating point standard."); 
#pragma STDC FENV_ACCESS ON 
int failed = std::fesetround(FE_TOWARDZERO); 
assert(!failed); 
if(x != 0 && std::isfinite(x) && std::isfinite(y)) 
    return y/x; 
else 
    throw std::invalid_argument("informative message"); 

Einige Compiler benötigen Nicht-Standardoptionen zur Aktivierung der vollständigen IEEE 754-Konformität (-frounding-math auf GCC).

+0

"Abhängig vom aktuellen Rundungsmodus" Dies ist kritisch, siehe 'fegetround' /' fesetround'. Wenn Sie auf Null runden, können Sie niemals ein Inf erhalten, wenn Sie durch einen endlichen Nicht-Null-Wert dividieren. – sbabbi

+0

Ich fühle mich wie fesetround ist nichts, das in einer leistungsempfindlichen Funktion aufgerufen werden sollte, oder? –

+0

@ruhigbrauner möglicherweise nicht. Sie möchten es möglicherweise außerhalb von Hot-Loops verschieben. – user2079303

5

Ja, schauen Sie sich Code unten

#include <iostream> 
int main() 
{ 
    double x = 1, y = 2; 
    while (y != 0) { 
     std::cout << y << " " << x/y << std::endl; 
     y /= 2; 
    } 
} 

irgendwann erhalten Sie:

8.9003e-308 1.12356e+307 
4.45015e-308 2.24712e+307 
2.22507e-308 4.49423e+307 
1.11254e-308 8.98847e+307 
5.56268e-309 inf 
2.78134e-309 inf 
1.39067e-309 inf 
6.95336e-310 inf