std::numeric_limits<int>::max() in ASCII Datei schreiben und wieder einlesen



  • Folgendes Problem

    double inf = std::numeric_limits<double>::max(); 
    //->inf = 1.7976931348623157e+308
    os<<setprecision(10);
    ofstream os("txt");
    os<<inf;
    
    ifstream is("txt");
    is>>inf; //->inf = -9.2559631349317831e+061
    

    Im ASCII File steht der Wert gerundet -> also grösser als std::numeric_limits<double>::max()
    Daher dachte ich, ich nehme einfach einen long double beim einlesen und setze inf auf max, wenn der wert grösser als max ist.

    geht aber auch nicht...

    Wie kann man hier konststent die Werte rausschreiben bzw. einlesen?


  • Administrator

    long double ist bei manchen Compilern nichts anderes als ein double . Für die tatsächlich Grösse musst du im Compilerhandbuch nachlesen.

    Zu deinem Problem, wieso nicht so?

    double inf = std::numeric_limits<double>::max(); 
    
    ofstream os("txt"); 
    os << setprecision(50);  // Gib ihm einfach genügend Präzision.
    os << inf; 
    
    ifstream is("txt"); 
    is >> inf;
    

    Grüssli



  • spontan fällt mir ein, bei der Ausgabe die Anzahl der Stellen derart anzugeben, dass der Wert ab- statt aufgerundet wird. Also entweder setprecision(8) oder 9 oder 12 - folgendes geht:

    #include <fstream>
    #include <limits>
    #include <iomanip>
    #include <iostream>
    
    int main()
    {
        using namespace std;
        double inf = std::numeric_limits<double>::max();
        //->inf = 1.7976931348623157e+308
        {
            ofstream os("txt");
            os<<setprecision(12);
            os<<inf;
        }
    
        ifstream is("txt");
        if( is>>inf )
        {   // inf = 1.79769313486e+308
            cout << "inf = " << inf << endl;
        }
        return 0;
    }
    

    das ist natürlich keine wirkliche Lösung - wozu möchtest Du 'numeric_limits<double>::max' überhaupt speichern?

    Gruß
    Werner



  • zum Serialisieren.
    Beim meinen Schedules (step, begin, end) ist das ende z.B. std. mäßig std::numeric_limits<double>::max(). Naja ud beim Einlesen soll das auch wieder drinn stehen. Binär ist das kein Thema. Aber ASCII soll es auch gehen.

    Und mit setprecision(50), kann man es nicht mehr ansehen 😃



  • Muss es von Menschen lesbar sein? Wenn nicht entweder die wahrscheinlich 8 Byte schreiben oder wenn es Editor lesbar sein soll dann die 8 Byte als 16 Hex Ziffern.

    EDIT: Eventuell auch 16 Hex Ziffern + die Ausgabe wie sie jetzt ist und beim einlesen nur die 16 Hex Ziffern beachten.



  • Ja, es soll von Menschen gelesen werden können (denn alles andere wird direkt binät geschrieben). Der Anwender soll hier ggf. die Grenzen selbst anpassen können.



  • muffmolch schrieb:

    zum Serialisieren.
    Beim meinen Schedules (step, begin, end) ist das ende z.B. std. mäßig std::numeric_limits<double>::max(). Naja ud beim Einlesen soll das auch wieder drinn stehen. Binär ist das kein Thema. Aber ASCII soll es auch gehen.

    Und mit setprecision(50), kann man es nicht mehr ansehen 😃

    Dann benutze

    setprecision(std::numeric_limits<double>::digits10+2)
    

    dann funktioniert auch:

    if( is>>inf )
        {
            cout << "inf = " << inf << endl;
            assert( inf == std::numeric_limits<double>::max() );
        }
    

    garantiert ist dieses Verhalten wahrscheinlich nicht. Ich würde ja statt dessen die Ausgabe von numeric_limits<double>::infinity() empfehlen, das kann aber zumindest mit VC9 dann nicht mehr gelesen werden.

    Gruß
    Werner



  • danke, werner. So werde ich das machen!

    wenn ich es richtig verstehe, dann entspricht digit10 den max nachkommastellen und das +2 der ersten Zahl ("1") und dem ".", ja?
    +2 für die erste Stelle + "."

    sollte dannfuer float analog gehen



  • muffmolch schrieb:

    wenn ich es richtig verstehe, dann entspricht digit10 den max nachkommastellen und das +2 der ersten Zahl ("1") und dem ".", ja?
    +2 für die erste Stelle + "."

    Nein nicht ganz - numeric_limits::digits10 ist lt. Standard: "Number of base 10 digits that can be represented without change." Also die Anzahl der Ziffern (im Dezimalsystem), die sicher dargestellt werden können. Wenn Du umgekehrt aber aus den Dezimalziffern sicher wieder binär die selbe double-Zahl haben willst, musst Du mehr Ziffern angeben.

    Anzahl Ziffern ist die Gesamtanzahl mit Vor- und Nachkommastellen. Wo das Komma steht ist irrelevant - das kann man ja über den Exponenten steuern.

    muffmolch schrieb:

    sollte dann fuer float analog gehen

    Im Prinzip Ja - aber probier's lieber nochmal aus.

    Gruß
    Werner


Anmelden zum Antworten