Die überprüfung, ob ein double (oder float) ist NaN in C++
Gibt es eine isnan () - Funktion?
PS.: Ich bin in MinGW (wenn das einen Unterschied macht).
Ich hatte das gelöst, indem Sie isnan() von <math.h>
, die nicht vorhanden ist <cmath>
, die ich war #include
ing auf den ersten.
Ich nicht rein, Sie können es tun portabel. Wer sagt, dass C++ erfordert IEEE754?
Siehe auch: wie erstelle ich eine portable isnan/isinf-Funktion
Nur eine Anmerkung, 1 Unze der Verhinderung ist besser als 1 Pfund Heilung. In anderen Worten, Verhinderung 0.f/0.f jemals ausgeführt wird ist weit besser, als nachträglich die Prüfung für
Das ist ein feature, bei dem zentrale Fehler überprüfen. Ebenso wie exceptions vs return values.
Warum nicht <cmath> isnan()? Es ist in std::
Siehe auch: wie erstelle ich eine portable isnan/isinf-Funktion
Nur eine Anmerkung, 1 Unze der Verhinderung ist besser als 1 Pfund Heilung. In anderen Worten, Verhinderung 0.f/0.f jemals ausgeführt wird ist weit besser, als nachträglich die Prüfung für
nan
's in deinem code. nan
ist kann furchtbar destruktiv, um Ihr Programm, wenn erlaubt, sich zu vermehren, die es einführen können schwer zu findende Fehler. Dies ist, weil nan
ist giftig, (5*nan
=nan
), nan
nicht gleich alles (nan
!= nan
), nan
nicht größer ist als alles (nan
!> 0), nan
ist nicht weniger als alles (nan
!< 0).Das ist ein feature, bei dem zentrale Fehler überprüfen. Ebenso wie exceptions vs return values.
Warum nicht <cmath> isnan()? Es ist in std::
InformationsquelleAutor hasen | 2009-02-20
Du musst angemeldet sein, um einen Kommentar abzugeben.
Gemäß der IEEE-Norm, NaN-Werte haben die merkwürdige Eigenschaft, dass Vergleiche mit Ihnen sind immer falsch. Das ist für einen Schwimmer f,
f != f
werden wahr nur wenn f NaN.Beachten Sie, dass, wie einige Kommentare weiter unten bereits erwähnt, nicht alle Compiler respektieren diese bei der Optimierung von code.
Für alle compiler, die behauptet, IEEE-floating-point -, dieser trick sollte Arbeit. Aber ich kann nicht garantieren, dass es wird Arbeit in der Praxis. Überprüfen Sie mit Ihrem compiler, wenn im Zweifel.
-1 funktioniert nur in der Theorie, nicht in der Praxis: Compiler wie g++ (mit -fastmath) Schraube, bis. die einzige Allgemeine Weise, bis c++0x, ist der test für bitpattern.
Die Dokumentation für die
-ffast-math
option explizit sagt, dass es kann führen zu falschen Ausgang für die Programme, die davon abhängen, eine genaue Umsetzung, wenn die IEEE-oder ISO-Regeln/Vorgaben für mathematische Funktionen. Ohne, dass die option aktiviert, mitx != x
ist eine durchaus gültige und tragbare Art und Weise der Prüfung für die NaN.die Dokumentation ist öffentlich erklären, dass es nicht-konforme, ja. und ja, ich habe festgestellt, dass argument vor, diskutieren diese ausgiebig mit Gabriel Dos Reis. es wird allgemein verwendet, um zu verteidigen, das design, die in einem zirkulären argument (ich weiß nicht, ob Sie beabsichtigt, zu verbinden, aber es lohnt sich zu wissen, über die -- es-flame-Krieg-Zeug). Ihre Schlussfolgerung, dass
x != x
gültig ist, ohne dass die option nicht logisch. es könnte wahr sein für eine bestimmte version des g++, oder nicht. sowieso, Sie haben in der Regel keine Möglichkeit zu garantieren, dass fastmath wird die option nicht verwendet werden.Nein, ich war nicht bewusst die Diskussion mit Gabriel Dos Reis. Steve Jessop machte einen großen Punkt in der anderen Frage, vorausgesetzt, IEEE-Darstellung. Wenn Sie davon ausgehen, IEEE 754, und dass der compiler in eine konforme Art und Weise (d.h. ohne die
-ffast-math
option), dannx != x
ist eine gültige und tragbare Lösung. Sie können sogar testen, für-ffast-math
durch die Prüfung für die__FAST_MATH__
makro-und schalten Sie auf eine andere Implementierung, in diesem Fall (z.B. mit unions und bit-twiddling).InformationsquelleAutor jalf
Gibt es keine
isnan()
- Funktion zur Verfügung, die in aktuellen C++ - Standard-Bibliothek. Es wurde eingeführt, C99 und definiert als ein makro keine Funktion. Elemente der standard-Bibliothek definiert, die von C99 sind nicht Teil des aktuellen C++ - standard ISO/IEC 14882:1998 weder die update-ISO/IEC 14882:2003.2005 Technischer Bericht 1 vorgeschlagen wurde. Die TR1 bringt Kompatibilität mit C99 auf C++. Trotz der Tatsache, es wurde nie offiziell verabschiedet zu werden C++ - standard, viele (GCC 4.0+ oder Visual C++ 9.0+ C++ - Implementierungen stellen TR1 bietet, alle oder nur einige (Visual C++ 9.0 nicht C99-math-Funktionen).
Wenn TR1 verfügbar ist, dann
cmath
C99 enthält Elemente wieisnan()
,isfinite()
usw. aber Sie sind definiert als Funktionen, keine Makros, üblicherweise instd::tr1::
namespace, obwohl viele Implementierungen (z.B. GCC 4+ auf Linux oder in XCode auf Mac OS X 10.5+) injizieren Sie direkt zustd::
, sostd::isnan
gut definiert ist.Außerdem werden einige Implementierungen von C++ noch machen C99
isnan()
Makros für C++ (durchcmath
odermath.h
), was zu noch mehr Verwirrungen und Entwickler können davon ausgehen, es ist ein standard-Verhalten.Einen Hinweis über die Viusal C++, wie oben erwähnt, ist es nicht
std::isnan
wederstd::tr1::isnan
, aber es stellt eine Erweiterung Funktion definiert als_isnan()
die seit Visual C++ 6.0Auf XCode, es ist sogar noch mehr Spaß. Wie bereits erwähnt, GCC 4+ definiert
std::isnan
. Für ältere Versionen von compiler und Bibliothek bilden, XCode, es scheint (hier ist relevante Diskussion), hatte noch keine chance zu testen, mich selbst) werden zwei Funktionen definiert, die__inline_isnand()
auf Intel-und__isnand()
auf Power-PC.Jeder will diese Funktionen wie isNan oder isInfinity. Warum haben die Verantwortlichen nicht einfach in Ihre standards???? - Ich werde versuchen, herauszufinden, wie man verantwortlich sein und meine Stimme in für diese. Ernst.
es ist Teil der C++11 en.cppreference.com/w/cpp/numeric/math/isnan
Im laden noch?
Diese Antwort sollte aktualisiert werden, da
std::isnan
ist jetzt Teil des C++11-standard und unterstützen ausgebreitet hat. std::isnan wurde implementiert in Visual Studio, beginnend mit Visual Studio 2013. Vielleicht @shuhalo bekam im laden 🙂InformationsquelleAutor mloskot
Erste Lösung: wenn Sie C++11
Da war gefragt, es gab wenig neue Entwicklungen: es ist wichtig zu wissen, dass
std::isnan()
ist Teil der C++11Synopsis
Definiert im header
<cmath>
Bestimmt, ob der angegebene Gleitkommazahl arg ist die not-a-number (
NaN
).Parameter
arg
: floating-point-WertRückgabewert
true
wenn argNaN
,false
sonstReferenz
http://en.cppreference.com/w/cpp/numeric/math/isnan
Bitte beachten Sie, dass dies unvereinbar mit dem -fast-math, wenn Sie g++, siehe unten für andere Vorschläge.
Andere Lösungen: wenn Sie mit nicht-C++11-konformen tools
Für C99, C, dies ist als makro implementiert
isnan(c)
zurückgibt, die einen int-Wert. Die Art derx
werden float, double oder long double.Verschiedenen Anbieter kann oder auch nicht oder keine Funktion ist
isnan()
.Den vermeintlich portable Weg, um zu überprüfen, für
NaN
ist zu verwenden das IEEE-754-Eigenschaft, dieNaN
ist nicht gleich zu sich selbst: d.h.x == x
wird false fürx
wirdNaN
.Jedoch die Letzte option funktioniert möglicherweise nicht mit jedem compiler und einige Einstellungen (insbesondere die Optimierung der Einstellungen), so dass im letzten Ausweg, können Sie immer überprüfen Sie die bit-Muster ...
-1
std::isnan
ist immer noch ein ungood Empfehlung von Jan 2017, da es nicht funktioniert mit g++'s floating-point-Optimierung.ist diese option IEEE-konform ? Die Antwort bearbeitet wurde
Beide
x != x
undisnan
erforderlich sind, um die Arbeit für die IEEE-754-compliance. Bezüglich der letzteren, die IEEE 754-2008 standard besagt, dass "Implementierungen stellt die folgende, nicht-rechnerische Operationen, die für alle unterstützten arithmetischen Formaten" und "isNaN(x) ist wahr, wenn und nur wenn x ein NaN". Für die überprüfung der Konformität, der standard erfordertis754version1985()
undis754version2008()
, wo C++ bietet stattdessenstd::numeric_limits<Fp>::is_iec559()
(IEC 559 ist der gleiche standard). Leider mit-ffast-math
Optimierung, z.B. g++ Ansprüche Konformität aber ist non-konform.0 das Entfernen meiner downvote, da die hinzugefügten Kommentar macht das Problem klar an den Leser. 🙂
InformationsquelleAutor BlueTrin
Gibt es auch eine header-only-Bibliothek präsentieren in Boost, die haben nette tools zum Umgang mit floating-point-Datentypen
Erhalten Sie die folgenden Funktionen:
Wenn Sie Zeit haben, dann haben Sie einen Blick auf ganze Mathe-toolkit von Boost, es hat viele nützliche tools und wächst schnell.
Auch beim Umgang mit schwimmenden und nicht-schwimmenden Punkte, es wäre eine gute Idee, sich an der Numerische Konvertierungen.
es wurde Hinzugefügt, Boost 1.35 (den ich gerade gefunden habe mein Programm nicht kompilieren auf alten linux-Distribution).
wenn Sie kompilieren mit der option --fast-math, dann ist diese Funktion nicht wie erwartet funktionieren.
InformationsquelleAutor Anonymous
Gibt es drei "offizielle" Wege: posix
isnan
makro, c++0xisnan
Funktion Vorlage, oder visual c++_isnan
Funktion.Leider ist es eher unpraktisch, zu erkennen, welche dieser zu nutzen.
Und leider gibt es keine zuverlässige Möglichkeit, um festzustellen, ob Sie IEEE-754-Darstellung mit NaNs. Die standard-Bibliothek bietet eine offizielle Weise (
numeric_limits<double>::is_iec559
). Aber in der Praxis-Compiler wie g++ - Schraube.In der Theorie könnte man einfach
x != x
, aber Compiler wie g++ und visual c++ - Schraube, bis.So dass am Ende-test für die spezifische NaN bitpatterns, vorausgesetzt (und hoffentlich durchsetzen, irgendwann!) eine Besondere Darstellung, wie IEEE 754.
BEARBEITEN: als Beispiel "Compiler wie g++ ... - Schraube-up", sollten Sie
Kompilieren mit g++ (TDM-2 mingw32) 4.4.1:
-ffast-math
option explizit sagt, dass es kann führen zu falschen Ausgang für die Programme, die davon abhängen, eine genaue Umsetzung, wenn die IEEE-oder ISO-Regeln/Vorgaben für mathematische Funktionen. Ohne, dass die option aktiviert, mitx != x
ist eine durchaus gültige und tragbare Art und Weise der Prüfung für die NaN.Was Sie übersehen ist, dass der C++ - standard nicht erforderlich, IEEE-Darstellung oder Mathematik für Schwimmer. So weit wie die Manpage dir sagt,
gcc -ffast-math
ist noch ein konformer C++ - Implementierung (gut, vorausgesetzt, es wirdnumeric_limits::is_iec559
Recht, es ist, obwohl Alf schlägt vor, dass es gar nicht): C++ - code unter Berufung auf IEEE ist nicht portable C++ und hat kein Recht zu erwarten-Implementierungen zu bieten.Und Alf ist richtig, quick-test auf gcc 4.3.4 und
is_iec559
gilt-ffast-math
. Also das problem ist hier, dass der GCC-Dokumentation für-ffast-math
nur sagen, dass es nicht dem IEEE-Standard/ISO für mathematische Funktionen, während Sie sollte sagen, dass es nicht in C++, da seine Umsetzung vonnumeric_limits
wird geschlafen. Ich würde vermuten, dass der GCC kann nicht immer sagen, zu der Zeit, die Vorlage wird definiert, ob die eventuelle backend hat eigentlich konform schwimmt, und so nicht einmal versuchen. IIRC gibt es ähnliche Probleme in der hervorragenden bug-Liste für GCC C99-Konformität.Ich wusste nicht, C++ - standard keine Spezifikation über das floating-point-Werte. Es ist ziemlich schockierend für mich. Es sieht eine bessere Handhabung IEEE-754 und NaN als Plattform-spezifische Erweiterung statt standard. Ist es nicht? Und kann ich erwarten, dass die jede Art von isnan() oder IEEE754 Hinzugefügt, die in C++0x?
C++0x noch hat zum Beispiel "Der Wert Darstellung von floating-point-Typen ist implementation-defined". C und C++ beide Zielen auf die Unterstützung Implementationen auf Maschinen mit nicht-Gleitkomma-hardware, und die ordnungsgemäße IEEE 754 floats kann durchaus ein bisschen langsamer zu emulieren als einigermaßen genaue alternativen. Die Theorie ist, die Sie geltend machen können
is_iec559
wenn Sie brauchen, IEEE, in der Praxis, dass scheint nicht zu funktionieren auf GCC. C++0x hat einenisnan
Funktion, aber da GCC nicht richtig umsetzenis_iec559
nun, ich denke, es wird nicht in C++0x und-ffast-math
könnte auch brechen Ihreisnan
.InformationsquelleAutor Cheers and hth. - Alf
Es ist ein std::isnan, wenn Sie-compiler unterstützt c99-Erweiterungen, aber ich bin mir nicht sicher, ob mingw nicht.
Hier ist eine kleine Funktion, die sollte funktionieren, wenn dein compiler nicht die standard-Funktion:
Wenn Sie tun, dass Ihre eine chance, die der compiler optimieren den Vergleich heraus, immer true zurückgeben.
Nein gibt es nicht. Ein compiler, der das tut, ist gebrochen. Genauso gut könnte man sagen, dass die chance besteht, dass die standard-Bibliothek
isnan
gibt das falsche Ergebnis. Technisch stimmt, der compiler könnte buggy sein, aber in der Praxis Nicht Passieren. Gleiche wievar != var
. Es funktioniert, weil das ist, wie IEEE-floating-point-Werte definiert sind.wenn -ffast-math wird festgelegt, isnan() nicht das richtige Ergebnis zurück, für den gcc. Natürlich, diese Optimierung ist dokumentiert, wie der Einbruch IEEE Semantik...
Wenn -ffast-math wird festgelegt, dann wird der compiler fehlerhaft ist. Oder vielmehr, wenn -ffast-math " eingestellt ist, werden alle Wetten sind aus, und Sie können nicht Sie verlassen sich auf NaNs sowieso.
InformationsquelleAutor CTT
Können Sie
numeric_limits<float>::quiet_NaN( )
definiert in derlimits
standard-Bibliothek zu testen. Es gibt eine separate Konstante definiert fürdouble
.Ich weiß nicht, ob dies funktioniert auf allen Plattformen, da ich nur getestet mit g++ unter Linux.
Gut zu wissen. Ich bin mit der version 4.3.2, so bin ich gut aus dem Wald.
InformationsquelleAutor Bill the Lizard
Können Sie die
isnan()
Funktion, aber Sie brauchen, um die C-math Bibliothek.Da diese Funktion ein Teil der C99 ist es nicht überall verfügbar ist. Wenn Ihr Lieferant nicht liefert die Funktion können Sie auch eigene Variante definieren, die für die Kompatibilität.
isnan
im <math.h>Wie gesagt, dies ist ein Teil der C99 ist. Als C99 ist nicht Teil der aktuellen C++ - standard, sofern ich die alternative. Aber wie es wahrscheinlich ist, dass isnan() werden in einer kommenden C++ - standard, habe ich eine #ifndef-Direktive um.
InformationsquelleAutor raimue
nan Prävention
Meine Antwort auf diese Frage ist nicht verwenden rückwirkend überprüft
nan
. Verwenden präventive Kontrollen für die Abteilungen der form0.0/0.0
statt.nan
Ergebnisse aus dem Betrieb0.f/0.f
oder0.0/0.0
.nan
ist eine schreckliche nemesis für die Stabilität Ihres Codes erkannt werden müssen und verhindert sehr sorgfältig1. Die Eigenschaften vonnan
, die sind anders als normale zahlen:nan
ist giftig, (5*nan
=nan
)nan
ist nicht gleich nichts, nicht einmal sich selbst (nan
!=nan
)nan
nicht größer ist als alles (nan
!> 0)nan
ist nicht weniger als alles (nan
!< 0)Den letzten 2 aufgeführten Eigenschaften sind Zähler-logische und führt zu ungewöhnlichem Verhalten von code, die sich auf Vergleiche mit einer
nan
- Nummer (die 3 letzten Eigenschaft ist seltsam, aber du bist wahrscheinlich nicht immer gehen, um zu sehenx != x ?
im code (es sei denn, Sie sind bei der Prüfung für nan (unzuverlässig))).In meinem eigenen code habe ich gemerkt, dass
nan
Werte tendenziell zu produzieren ist schwierig, Fehler zu finden. (Beachten Sie, wie das ist nicht Fall fürinf
oder-inf
. (-inf
< 0) gibtTRUE
, ( 0 <inf
) gibt TRUE zurück, und auch (-inf
<inf
) gibt TRUE zurück. Also, meiner Erfahrung nach, das Verhalten des Codes ist oft noch wie gewünscht).was zu tun ist, unter nan
Was Sie wollen passieren unter
0.0/0.0
behandelt werden muss als ein besonderer Fall, aber was Sie tun müssen, hängt von den zahlen, die Sie erwarten, dass aus dem code.Im obigen Beispiel wird das Ergebnis von (
0.f/FLT_MIN
)0
im Grunde. Sie Mai wollen0.0/0.0
zu generierenHUGE
statt. So,So, in den oben genannten, wenn x
0.f
,inf
führen würde (das hat ziemlich gut/nicht-destruktive Verhalten, wie oben erwähnt, eigentlich).Erinnern, integer-division durch 0 wird eine Laufzeit-exception. So muss man immer überprüfen, für die division durch 0. Nur weil
0.0/0.0
leise ausgewertetnan
bedeutet nicht, Sie können faul sein und nicht überprüfen0.0/0.0
bevor es passiert.1 Prüfungen für
nan
überx != x
sind manchmal unzuverlässig (x != x
bestrichen werden durch einige Optimierung der Compiler, dass die Pause IEEE-compliance, insbesondere dann, wenn der-ffast-math
- Schalter aktiviert ist).Beachten Sie, dass 0.0/0.0 ist nicht der einzige Vorgang, der möglicherweise in einem NaN. Die Quadratwurzel einer negativen Zahl gibt NaN. Der Cosinus +infinity NaN zurück als gut. die operation acos(x), wobei x nicht in den Bereich [0,pi] kann auch zum Ergebnis NaN. Kurz gesagt, man muss besonders vorsichtig sein, um auch einen Blick auf diese potenziell riskante Vorgänge, nicht nur um 0.0/0.0.
Stimme völlig mit Boris. In meiner Erfahrung, NaN praktisch immer kam so etwas wie sqrt(-1.302 e-53), D. H. fast-zu-null-intermediate-Berechnung Ergebnisse eingespeisten sqrt ohne zu prüfen, für Negativität.
InformationsquelleAutor bobobobo
Der folgende code verwendet die definition von NAN (alle Exponenten-bits, mindestens eine gebrochene bit gesetzt) und geht davon aus, dass sizeof(int) = sizeof(float) = 4. Sie können look-up-NAN in der Wikipedia für die details.
bool IsNan( float value )
{
return ((*(UINT*)&value) & 0x7fffffff) > 0x7f800000;
}
Ich glaube, das funktioniert auch auf big-endian-Plattformen. Die wörtliche
0x7fffffff
würde einfach sitzen im Speicher alsff ff ff 7f
.value
hat die gleiche Bestellung wie0x7f800000
, so werden alle Operationen, die line-up (es gibt kein vertauschen von bytes). Mich würde interessieren, wenn das jemand testen könnte das auf einer big endian Plattform.InformationsquelleAutor Ian
Dies funktioniert, wenn
sizeof(int)
4 und diesizeof(long long)
8.Während der Laufzeit ist es nur der Vergleich, Guss-nehmen Sie keine Zeit. Es ändert nur den Vergleich flags Konfiguration zu überprüfen Gleichheit.
Beachten Sie, dass diese Besetzung bricht die strict-aliasing-Regel, die mit g++, und dass compiler bekannt, um zu tun, Unaussprechlichen Dinge™, wenn es erkennt, formale UB. Statt effiziente wirft, die mit g++, die Sie verwenden müssen
memcpy
durch ein byte-array um sicher zu sein. Code für die, die in meiner #2 Antwort.InformationsquelleAutor ST3
Als von C++14 gibt es eine Reihe von Möglichkeiten, um zu testen, ob eine floating-point-Zahl
value
ist ein NaN.Dieser Hinsicht nur überprüfung des bits der Zahl-Darstellung,
funktioniert zuverlässig, wie bereits in meiner ursprünglichen Antwort. Insbesondere
std::isnan
und die oft vorgeschlagene checkv != v
, funktionieren nicht zuverlässig und sollte nicht verwendet werden, damit dein code funktioniert korrekt, wenn jemand entscheidet, dass floating-point-Optimierung benötigt wird, und fordert den compiler zu tun. Diese situation kann sich ändern, Compiler kann mehr konform, aber für dieses Problem nicht passiert in den 6 Jahren seit der ursprünglichen Antwort.Seit ungefähr 6 Jahren meine ursprüngliche Antwort war die gewählte Lösung für diese Frage, das war OK. Aber vor kurzem ein hoch von Ihnen positiv bewertet werden Antwort die Empfehlung der unzuverlässige
v != v
test ausgewählt wurde. Daher ist diese zusätzliche mehr up-to-date-Antwort (wir haben jetzt die C++11 und C++14-standards, und C++17 auf den Horizont).Die wichtigsten Möglichkeiten, um zu überprüfen für NaN-heit, als von C++14, sind:
std::isnan(value) )
ist der vorgesehene standard-Bibliothek seit C++11.
isnan
offenbar Konflikte mit derPosix-Makros mit dem gleichen Namen, aber in der Praxis ist das kein problem. Das Hauptproblem ist
dass, wenn die floating point Arithmetik Optimierung angefordert wird, dann mit mindestens einem Haupt-compiler, nämlich g++,
std::isnan
zurückfalse
für NaN argument.(fpclassify(value) == FP_NAN) )
Leidet unter dem gleichen problem wie
std::isnan
, d.h., ist nicht zuverlässig.(value != value) )
Empfohlen, SO viele Antworten. Leidet unter dem gleichen problem wie
std::isnan
, d.h.,ist nicht zuverlässig.
(value == Fp_info::quiet_NaN()) )
Dies ist ein test, der mit standard-Verhalten, sollten Sie nicht erkennen, NaNs, aber das mit dem
optimierte Verhalten vielleicht erkennen könnte NaNs (aufgrund der optimierten code nur der Vergleich der
bitlevel-Darstellungen direkt), und vielleicht kombiniert mit einer anderen Art und Weise zu
decken Sie die standard un-optimierte Verhalten, könnte zuverlässig erkennen NaN. Leider
es stellte sich heraus, nicht zuverlässig arbeiten.
(ilogb(value) == FP_ILOGBNAN) )
Leidet unter dem gleichen problem wie
std::isnan
, d.h., ist nicht zuverlässig.isunordered(1.2345, value) )
Leidet unter dem gleichen problem wie
std::isnan
, d.h., ist nicht zuverlässig.is_ieee754_nan( value ) )
Dies ist keine standard-Funktion. Es ist die überprüfung der bits nach IEEE 754
standard. Es ist völlig zuverlässig aber der code ist etwas systemabhängig.
In der folgenden kompletten test-code "Erfolg" ist, ob ein Ausdruck von berichten Nan-ness der Wert. Für die meisten Ausdrücke dieser Maßnahme der Erfolg, das Ziel der Aufdeckung von NaNs und nur NaNs, entspricht der standard-Semantik. Für die
(value == Fp_info::quiet_NaN()) )
Ausdruck, aber das standard-Verhalten ist, dass es nicht funktioniert NaN-Detektor.Ergebnisse mit g++ (beachten Sie wieder, dass das standard-Verhalten von
(value == Fp_info::quiet_NaN())
ist, dass es nicht funktioniert, als ein NaN-Detektor, es ist einfach sehr viel praktisches Interesse hier):Ergebnisse mit Visual C++:
Fasst die oben genannten Ergebnisse, nur die direkten Tests der bit-level-Darstellung, mit der
is_ieee754_nan
Funktion definiert, in diesem test-Programm, arbeitet zuverlässig in allen Fällen, sowohl mit g++ und Visual C++.Nachtrag:
Nach der Veröffentlichung des oben wurde mir bewusst, dass noch ein weiterer möglicher test für NaN, erwähnt in eine andere Antwort hier, nämlich
((value < 0) == (value >= 0))
. Dass sich herausstellte, funktioniert mit Visual C++, scheiterte aber mit g++'s-ffast-math
option. Nur direkte bitpattern-Prüfung zuverlässig funktioniert.InformationsquelleAutor Cheers and hth. - Alf
Eine mögliche Lösung, die nicht abhängig von den spezifischen IEEE-Repräsentation für NaN verwendet, wäre die folgende:
InformationsquelleAutor Dan Nathan
Als für mich die Lösung könnte sein, ein makro, um es explizit inline-und damit schnell genug.
Es funktioniert auch für jeden float-Typ. Es basiert auf der Tatsache, dass der einzige Fall, Wann ein Wert nicht gleich selbst, wenn der Wert keine Zahl ist.
Einige Compiler kann optimieren von code.
Andere Antworten zeigen, dass dies ein Fehler mit -ffast-math-option eingestellt.
InformationsquelleAutor user1705817
Wenn man bedenkt, dass (x != x) ist nicht immer gewährleistet, für NaN (z.B. wenn Sie das -ffast-math-option), habe ich mit:
Zahlen können nicht beide < 0 und >= 0, so wirklich diese Prüfung nur bestanden, wenn die Zahl weder kleiner, noch größer als oder gleich null ist. Das ist im Grunde keine Zahl oder NaN.
Könnte man dieses auch verwenden, wenn Sie bevorzugen:
Ich bin mir nicht sicher, wie das beeinflusst wird durch -ffast-math, obwohl, so kann Ihre Laufleistung variieren.
f != f
ist fehlerhaft auch. Ich habe gesehen, llvm Optimierung einen nahezu identischen Stück code entfernt. Der Optimierer kann verbreiten Sie die Informationen über die erste-Vergleich und herausfinden, dass der zweite Vergleich kann niemals wahr sein, wenn Sie die erste ist. (wenn der compiler hält sich strikt an die IEEE-Regelnf != f
ist viel einfacher sowieso)Funktioniert nicht mit g++'s
-ffast-math
option. Funktioniert mit Visual C++. Siehe (stackoverflow.com/a/42138465/464581).InformationsquelleAutor Jerramy
Dies funktioniert:
Ausgabe: isnan
InformationsquelleAutor edW
Scheint es mir, dass die besten wirklich cross-Plattform-Ansatz wäre die Verwendung einer union und zu testen, die bit-Muster der double check für NaNs.
Habe ich nicht gründlich getestet, diese Lösung, und es kann eine effizientere Art zu arbeiten, mit der bit-Muster, aber ich denke, dass es funktionieren sollte.
InformationsquelleAutor Sheldon Juncker
Den IEEE-standard sagt
wenn die Exponenten aller 1s
und
Mantisse nicht null ist,
die Zahl ist ein NaN.
Doppel-ist 1 Vorzeichen-bit, 11 Exponenten-bits und die Mantisse 52 bits.
Ein bisschen überprüfen.
InformationsquelleAutor bop
Dieser erkennt, infinity und auch NaN in Visual Studio, indem es die Kontrolle ist innerhalb von doppelten Grenzen:
InformationsquelleAutor mathengineer
Als Kommentare über den Staat != eine wird nicht funktionieren, die in g++ und einige andere Compiler, aber diesen trick sollten. Es ist vielleicht nicht so effizient, aber es ist noch ein weiter Weg:
Grundsätzlich in g++ (ich bin mir nicht sicher über andere obwohl) printf gibt 'nan' auf %d oder %.f-Formate, wenn variable is not a valid integer/float. Also dieser code ist die Prüfung für das erste Zeichen des Strings 'n' (wie in "nan")
Ja t', oder
340282346638528859811704183484516925440.000
wenn a=FLT_MAX
. Er würde verwendenchar s[7]; sprintf(s, "%.0g", a);
, die werden 6 chrs, wenna=-FLT_MAX
oder-3e+38
InformationsquelleAutor ZenJ