double - double = nan ???
-
Hi,
ich habe in meinem Programm folgende Zeilen:
double* point = ug0->GetPointData()->GetVectors()->GetTuple3(i); // simpe calculation double temp = sqrt(point[0] * point[0] + point[1] * point[1] + point[2] * point[2]); // calculation with norm function double temp2 = vtkMath::Norm(point, 3); cout << "Difference: " << (temp2 - temp) << endl;Eigenltlich sollte die Differenz immer Null ergeben. Ich weiss, mit der Null ist das so ne Sache in der Informatik (Maschinengenauigkeit)...
Folgende Ausgabe wird erzeugt:
nan
nan
0
nan
nan
nan
nan
0
0
0
nan
0
0
0Was bedeutet nan? "Not A Number" hab ich mehrfach im Internet gefunden. Was bedeutet das für mich? Ist temp = temp2, falls die Differenz beider nan ergibt?
Kann man mit 'nan' rechnen wie mit '0'? Das dürfte ja nicht gehen, wenn es keinen Zahl ist.Gruss, K.B.
-
NaN entsteht, wenn eine Rechenoperation undefinierte Werte zurückliefert (z.B. die Wurzel aus einer negativen Zahl). Und wirklich damit rechnen kannst du leider nicht - wenn ein Operand NaN ist, kommt als Ergebnis wieder NaN heraus.
Für weitere Informationen empfehle ich z.B. das Wikipedia: NaN
-
Mit welchen Zahlen hat man es zu tun?
Mach mal ein vollständiges lauffähiges Programm, das den Fehler zeigt.
-
unter drei bedingungen, die hier zu nan führen können:
- point[0] * point[0] + point[1] * point[1] + point[2] * point[2] ist unendlich, dann ist auch die wurzel daraus unendlich, die differenz zweier unendlichkeiten ist allerdings nan
- wenigstens eine der komponenten von point ist bereits ein nan
- vtkMath::Norm produziert möglicherweise auch sonst nans - code fehltdenkbar wäre, dass du irgenwann versucht hast, einen 0-vektor zu normieren (division durch 0 führt zu unendlichkeiten in den komponenten und der erste fall tritt ein).
-
Gibt mal noch die Werte von 'temp' und 'temp2' aus, denn einer der Werte müßte dann ja NaN sein.
-
Hi,
danke für die Infos. Tatsächlich steckt in einem der Point[i] bereits das nan oder ein inf.
Ich habe die Spur zurückverfolgt und bin an nun an einer Stelle, die nan, inf und -inf liefern kann. Diese Funktion soll nicht abgeändert werden. Ich möchte nun aber die Fälle nan, inf und -inf abfangen und gesondert behandeln. Wie funktioniert das?
double a = EineFunktion(...); // liefert meist ein gültigen Double-Wert, ab und an auch nan, inf oder -inf if (a == inf) ...Sowas geht leider nicht.
Gibts eine andere Möglichkeit?Gruss, K.B.
-
das läßt sich recht leicht durch ein paar einfache funktionen machen, etwa
bool is_nan(double x) { return x != x; } bool is_pos_inf(double x) { static double null = 0; static const double inf = 1 / null; return x == inf; } bool is_neg_inf(double x) { static double null = 0; static const double inf = -1 / null; return x == inf; }
-
Das macht man besser mit Standardmitteln machen. Man will doch keine SIGFPE erhalten.
if (d == std::numeric_limits<double>::infinity()) { std::cout << "d is infinity\n"; }
-
Hi,
die Abfrage mit std::numeric_limits<double>::infinity() funktioniert einwandfrei! Schonmal besten Danke für den Hinweis.
Unter http://gcc.gnu.org/onlinedocs/libstdc++/latest-doxygen/structstd_1_1numeric__limits.html gibts auch entsprechende Funktionen quiet_NaN()und signaling_NaN(). Diese fangen ein NaN in meinem Fall nicht ab. Ich verstehe auch nicht so recht was quiet_NaN()und signaling_NaN() machen soll.
Als nächstes habe ich (var == 0.0 / 0.0) probiert. Dies konnte die Variablen auch nicht finden.Mit (var != var) hat es schließlich geklappt. Aber ich verstehe nicht warum. Ist denn NaN und NaN nicht das gleiche?
Gruss, K.B.
-
Karl Blau schrieb:
Ist denn NaN und NaN nicht das gleiche?
Nein - NaN hat die (un)schöne Eigenschaft, daß jeder Vergleich damit "false" ergibt (selbst wenn die Werte identisch sind). Deshalb wird "x==quiet_NaN();" auch niemals true zurückliefern.
PS: alternativ zu der "x!=x" Variante könntest du die Werte auch binär miteinander vergleichen (per memcmp()).