Wie überprüfen Sie für unendliche und unbestimmte Werte in C ++?
-
03-07-2019 - |
Frage
In meinen Programmen Unendlichkeit entsteht in der Regel, wenn ein Wert von Null geteilt wird. Ich unbestimmt, wenn ich Null durch Null teilen. Wie überprüfen Sie für unendliche und unbestimmte Werte in C ++?
In C ++, Unendlichkeit wird durch 1. # INF vertreten. Unbestimmte wird dargestellt durch -1. # IND. Das Problem ist, wie man testen, ob eine Variable unendlich oder unbestimmt ist. Unendlich Überprüfung ist relativ einfach: Sie können die Unendlichkeit Definition in Ihrem speziellen C ++ finden. Für meinen Fall (VS2003), es ist std :: numeric_limits :: unendlich (). Sie müssen „Grenzen“ enthalten, um es zu benutzen. Sie können diesen unendlichen Wert einer Variablen zuweisen und Sie können es bis zu einem gewissen Wert vergleichen, um zu überprüfen, ob dieser Wert unendlich ist.
Unbestimmte ist ein wenig schwierig, weil man nicht einen unbestimmten Wert auf einen anderen Wert vergleichen. Jeder Vergleich gibt false zurück. Sie können diese Eigenschaft verwenden, um einen unbestimmten Wert zu erfassen, indem sie sich selbst zu vergleichen. Angenommen, Sie haben eine doppelte variable aVal genannt haben. Unter normalen Bedingungen gibt aVal! = AVal false. Aber wenn der Wert unbestimmt ist, aIndVal! = AIndVal gibt true zurück. Diese seltsame Situation für unendliche Werte nicht vorhanden ist, das heißt aInfVal! = AInfVal immer false zurück.
Hier sind zwei Funktionen, die verwendet werden können, für unbestimmte und unendliche Werte zu prüfen:
#include "limits.h"
#include "math.h"
bool isIndeterminate(const double pV)
{
return (pV != pV);
}
bool isInfinite(const double pV)
{
return (fabs(pV) == std::numeric_limits::infinity())
}
Gibt es bessere Möglichkeiten für diese Kontrollen, bin ich etwas fehlt?
Lösung
Für Visual Studio würde ich verwenden _isnan
und _finite
oder vielleicht _fpclass
.
Aber wenn Sie haben Zugang zu einer C ++ 11-Lage-Standardbibliothek und Compiler Sie std::isnan
und std::isinf
.
Andere Tipps
Obwohl C ++ 03 bietet keine C99 isnan und isinf Makros , C ++ 11 standardisiert sie von ihnen als Funktionen bieten. Wenn Sie C ++ 11, statt streng C ++ 03 verwenden können, dann würden diese Reiniger Optionen sein, die von Makros zu vermeiden, Compiler Einbauten und plattformabhängige Funktionen.
C ++ 11 std::isfinite
Renditen true
für alle Werte außer inf
und nan
; so !isfinite
sollte für unendliche und unbestimmte Werte in einem Schuss überprüfen.
Obwohl nicht unbedingt ein Teil von C ++ 03, wenn Ihr Compiler einige der neuen C99 Features des Standard bietet isfinite
, isinf
, isnan
. Wenn ja, wäre dies die einfachste und sicherste Weg, um diese Kontrollen durchzuführen.
Sie können auch diese als strenge C ++ verwenden - einzige Lösung. Sie bieten nicht wirklich mehr als die Lösung des OP außer zusätzliche Sicherheit durch die Verwendung von Typ Zügen und vielleicht den kleinsten Geschwindigkeitsschub im Fall von is_inf
.
template <bool> struct static_assert;
template <> struct static_assert<true> { };
template<typename T>
inline bool is_NaN(T const& x) {
static_cast<void>(sizeof(static_assert<std::numeric_limits<T>::has_quiet_NaN>));
return std::numeric_limits<T>::has_quiet_NaN and (x != x);
}
template <typename T>
inline bool is_inf(T const& x) {
static_cast<void>(sizeof(static_assert<std::numeric_limits<T>::has_infinity>));
return x == std::numeric_limits<T>::infinity() or x == -std::numeric_limits<T>::infinity();
}
(Vorsicht selbstgemachter static_assert
)
Es gibt isfinite
von C99 oder POSIX oder etwas, was ich denke.
Ein hackish Weg, es zu tun ist, x-x == 0
zu testen; wenn x
unendlich oder NaN ist, dann x-x
ist NaN so der Vergleich fehlschlägt, während, wenn x
endlich ist, dann x-x
0
ist und der Vergleich erfolgreich ist. Ich würde empfehlen, isfinite
verwenden, obwohl, oder die Verpackung diesen Test in eine Funktion / Makro etwas wie isfinite
genannt, so dass Sie es loswerden kann alles, wenn die Zeit kommt.
if (x!=x) ... then x is nan
if (x>0 && x/x != x/x) ... then x is +inf
if (x<0 && x/x != x/x) ... then x is -inf
Dies könnte funktionieren auch (aber beinhaltet nennen exp () und Gleichheit der Doppel Prüfung):
if (exp(-x)==0.) ... then x is inf
if (exp(x)==0.) ... then x is -inf