Frage

Was ist der beste Weg, NaNs in C ++ verwenden?

fand ich std::numeric_limits<double>::quiet_NaN() und std::numeric_limits<double>::signaling_NaN(). Ich möchte signaling_NaN verwenden, um eine nicht initialisierte Variable darzustellen, wie folgt:

double diameter = std::numeric_limits<double>::signaling_NaN();

Dies ist jedoch Signale (eine Ausnahme auslöst) auf Zuordnung. Ich will es eine Ausnahme bei der Verwendung erhöhen, nicht auf Zuordnung.

Gibt es eine Möglichkeit signaling_NaN zu verwenden, ohne eine Ausnahme auf Zuweisung zu erhöhen? Gibt es eine gute, tragbare Alternative zu signaling_NaN, die eine Gleitkomma-Ausnahme wird erhöhen, wenn verwendet?

War es hilfreich?

Lösung

Nach etwas mehr in diese suchen, sieht es aus wie signaling_NaN nutzlos ist wie vorgesehen. Wenn Gleitkomma-Ausnahmen aktiviert sind, dann ruft es zählt als Verarbeitung eines Signalisierungs NaN, so dass er wirft sofort eine Ausnahme. Wenn Gleitkomma-Ausnahmen deaktiviert sind, wird die Verarbeitung einer Signalisierungs NaN automatisch in einer ruhigen NaN degradiert, so signaling_NaN funktioniert nicht oder so.

Menkboy Code funktioniert, aber versuchen Signalisierung NaNs zu verwenden läuft in andere Probleme: es gibt keine tragbare Art und Weise Gleitkomma-Ausnahmen zu aktivieren oder deaktivieren (wie erwähnt href="https://stackoverflow.com/questions/85726/converting-floating-point-exceptions-into-c-exceptions#88829"> hier und hier ), und wenn Sie auf Ausnahmen angewiesen sind wird aktiviert , Code von Drittanbietern kann sie deaktivieren (wie hier ).

So wie es scheint, Motti Lösung ist wirklich die beste Wahl.

Andere Tipps

Was signalisiert NAN bedeutet, dass, wenn die CPU es trifft ein Signal ausgelöst wird, (daher der Name). Wenn Sie nicht initialisierte Variablen erkennen wollen, dann die Warnstufe auf Ihrem Compiler Anhebung erkennt in der Regel alle Pfade, die uninitalized Werte verwenden. Andernfalls, dass Sie eine Wrapper-Klasse verwenden können, die einen boolean speichert sagen, wenn der Wert initialisiert:

template <class T>
class initialized {
    T t;
    bool is_initialized;
public:
    initialized() : t(T()), is_initialized(false) { }
    initialized(const T& tt) : t(tt), is_initialized(true) { }
    T& operator=(const T& tt) { t = tt; is_initialized = true; return t; }
    operator T&() {
         if (!is_initialized)
             throw std::exception("uninitialized");
         return t; 
   }
};

Sie können eine Signalisierung NaN in eine Variable schreiben, ohne das Auslösen einer Ausnahme mit so etwas wie dieses (nb: nicht getestet)

void set_snan( double &d )
{
    long long *bits = (long long *)&d;
    *bits = 0x7ff0000080000001LL;
}

Es wird den meisten Orten arbeiten, aber nein, es ist nicht zu 100% tragbar.

Nun, auf der Suche nach der Definition des sowohl ruhig und Signal NaN, kann ich nicht wirklich einen Unterschied ausmachen.

Sie können den Code verwenden, die sich in diesen Funktionen verwendet wird, vielleicht verhindert es eine Ausnahme, dass Art und Weise, aber in diesen beiden Funktionen keine Ausnahme zu sehen, denke ich, es könnte sonst etwas in Beziehung gesetzt werden.

Wenn Sie möchten, um direkt den NaN zuweisen:

double value = _Nan._Double;

Einfache Antwort: Tun Sie etwas, wie dies in der Header-Datei und verwenden Sie es überall sonst:

#define NegativeNaN log(-1)

Wenn Sie ihnen irgendeine Art von Manipulationen tun besser schreiben einige erweiterte Wrapper-Funktion um exp() wie extended_exp() und so weiter!

Ihre C ++ Implementierung kann eine API für die Floating-Point-Umgebung Zugriff zu testen und klar bestimmten Punkt schwebende Ausnahmen. Siehe meine Antwort auf eine ähnliche Frage für weitere Informationen.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top