float/double nan zuweisen?



  • hi, zwei Fragen:

    • wie kann ich einem Float oder Doublewert NaN/+Inf/-Inf zuweisen?
      Ich hab da kein symbol für finden können.
    • wenn ich einen solchen Double habe und ihn rausschreibe (stream) schreibt er sowas wie: -1.0000#inf, wenn ich das einlese bekomme ich -1.0 😞
      Wie kann ich einen NaN/Inf mit einem stream einlesen ( instream >> doubleVar), ohne dass ich den stream selbst parsen muss?

    Gruß,
    vlad



  • Zum ersten Punkt: double myNan = 0.0/0.0;

    Sonst:

    #include <cmath>
    
    double myNan = NAN;
    double myInf = INFINITY;
    

    Problem dabei ist, das es nicht nur einmal NaN gibt, sondern so einige (Millionen?) und auch noch quiet NaNs und signalling NaNs. Letztere willst du wohl nicht haben wollen, daher probier mal NAN aus.



  • Zum ersten Punkt: double myNan = 0.0/0.0;

    Das gibt ein Kompilererror, da muss man zusätzlich ne temporäre variabe nehmen.
    Das checkt dann aber möglicherweise die nächste Kompilerversion

    Gibt es dafür wirklich keine andere Möglichkeit?

    Edit:
    NAN und INFINITY gibts bei mir net (VS2005)



  • für 'ne windows-kiste z.b.

    void main (void)
    {
      double d;
    
      *(__int64*)&d = 0x7FF0000000000000;   // + inf
      printf ("%f\n", d);
    
      *(__int64*)&d = 0xFFF0000000000000;   // - inf
      printf ("%f\n", d);
    
      *(__int64*)&d = 0x7FF8000000000000;   // nan
      printf ("%f\n", d);
    }
    

    ^^ist natürlich höchst unportabel
    🙂



  • ==>2^(size_of(float)*8)+1
    geht das? oder zählt der von vorn. theoretisch müsste das von vorne losgehen, aber bei einem älteren programm hats anscheinend irgendwann ein ininity gegeben, als ich immer weiter aufaddierte.



  • Hm, g++ gibt zwar eine Warning aus bei 0.0/0.0 aber ansonsten funzt das.
    Wie sieht es mir sqrt(-1) aus?



  • So:

    #include <iostream>
    #include <limits>
    
    int main()
    
    {
        {
            float nan  = std::numeric_limits<float>::quiet_NaN();
            float inf  = std::numeric_limits<float>::infinity();
            float ninf = -std::numeric_limits<float>::infinity();
            std::cout << nan << '\n';
            std::cout << inf << '\n';
            std::cout << ninf << '\n';
        }
    
        {
            double nan  = std::numeric_limits<double>::quiet_NaN();
            double inf  = std::numeric_limits<double>::infinity();
            double ninf = -std::numeric_limits<double>::infinity();
            std::cout << nan << '\n';
            std::cout << inf << '\n';
            std::cout << ninf << '\n';
        }
    }
    

    Und ob bestimmte Dinge zur Verfügung stehen (z.B. signaling NaNs) lässt sich auch prüfen:

    std::cout << std::boolalpha << std::numeric_limits<float>::has_signaling_NaN << '\n';
    


  • std::numeric_limits<>::infinity|quiet_NaN|signaling_NaN()

    PS: zu spät 😞



  • prima, das habe ich gesucht.
    Muss man mal drauf kommen, dass sowas in numerical limits steht.

    jetzt bleibt noch das stream problem.



  • vlad_tepesch schrieb:

    prima, das habe ich gesucht.
    Muss man mal drauf kommen, dass sowas in numerical limits steht.

    jetzt bleibt noch das stream problem.

    Das musst Du wohl oder übel parsen. Es gibt zwar istream Implementierungen, die nan erkennen, aber das ist im Standard so nicht definiert.



  • 😞
    Ok, trotzdem Danke.



  • Für was willst Du denn den Wert NaN eigentlich haben? Willst Du damit vergleichen, à la if(value == NaN) , oder willst Du nur irgendeinen NaN Wert haben, um damit rumzuspielen?
    Der Vergleich wird nämlich mit hoher Wahrscheinlichkeit so nicht klappen, da es, wie Fellhuhn schon sagte, jede Menge Bitmuster gibt, die NaN sind.
    Auf NaN kann man am besten Prüfen, indem man einen Wert auf Gleichheit mit sich selbst prüft. Das gibt im Falle von Wert = NaN nämlich immer Flasch:

    float someValue = //irgendwas, das NaN ergibt...
    //...
    if(someValue == someValue)
    {
    //nicht NaN...
    }
    else
    {
    //NaN
    }
    


  • Oder man benutzt isnan(x) aus cmath. Was der Makro genau macht, weiß ich jetzt aber auch nicht ohne nachzugucken. 😉



  • Fellhuhn schrieb:

    Oder man benutzt isnan(x) aus cmath. Was der Makro genau macht, weiß ich jetzt aber auch nicht ohne nachzugucken. 😉

    Ist das im Standard? Ich denke, eher nicht.



  • in einem geordneten vektor dürfen werte fehlen.
    Da die Werte aber feste stellen im Vektor haben, muss das Fehlen des Wertes ja irgendwie gekennzeichnet werden.

    Außerdem muss ich diese vektoren abspeichern und einlesen



  • isnan ist C99. Im g++ im pedantic-Mode wurde das bei mir nicht akzeptiert.

    Vergleiche mit (Signaling-)NaNs sind außerdem böse. Unter Tru64 z.B. gibt das sofort eine Floating Point Exception.

    Da es isnan in C++ 98/2003 nicht gibt und Vergleiche mit Signaling NaNs böse sind, kann man AFAIK nicht völlig standardkonform auf NaN vergleichen.



  • was ist flasch an
    if(!nanVar==nanVar)
    ?

    IEEE 754 schreibt vor, dass Vergleiche mit einem nan immer false liefern.

    und dass es hier ja um quiet nans geht ist logisch. Ergibt schließlich schon aus der Fragestellung;



  • Der Standard schreibt zumindest keine Speicherung als IEEE 754 vor, oder irre ich mich da?

    AFAIK bieten viele Compiler die Möglichkeit an, IEEE 754 konformen Code zu generieren, allerdings mit (je nach dem was man macht) Geschwindigkeitseinbußen.

    numeric_limits bietet aber is_iec559() (IEC559 entspricht IEEE754).

    P.S.:
    Ich kann für meinen Teil nur sagen, dass ich mit derartigen Vergleichen schon ziemlich böse auf die Nase gefallen bin, als ich etwas vermutlich ähnliches zu deiner Frage versucht habe (De/Serialisierung von doubles zwischen verschiedenen Hardware-Plattformen).



  • nanVar == nanVar geht natürlich. Man sollte aber auf keinen Fall einen entsprechenden Kommentar im Code vergessen, denn sowas wird gerne mal als "unsinnig" von anderen entfernt, die mit dem Thema noch nicht zu kämpfen hatten. Denn nan ist wie ein Virus, hat man ihn einmal verbreitet er sich im ganzen System und dann ist es schwer herauszufinden wo er herkommt. 😉

    Gerade mal geschaut: math.h nutzt __isnan. Wie ein nan aussieht ist definiert in bits/nan.h (__nan_bytes => __nan_union => NAN). Zumindest bei mir hier. 😉


Anmelden zum Antworten