Fragen zu 128-Bit Integer



  • Haha. Das ist nicht dein Ernst, oder?



  • ???
    Naja, es funktioniert und ich sagte doch auch, dass ich die Lösung noch nicht perfekt finde. Ich wäre natürlich lieber an einer statischen Lösung interessiert, aber die einzige statisch funktionierende Lösung hier, setzt GCC/g++ mit "-std=c99" voraus. Ich verwende aber "-std=c++0x" und möchte auch dabei bleiben.



  • Du leckst Speicher wie ein Küchensieb; ich würde das nicht als "funktioniert tadellos" bezeichnen.

    Die Frage ist ein bisschen, was du eigentlich willst. Die grundlegende Funktionalität lässt sich auf verschiedene Arten umsetzen; schwierig ist allein der syntaktische Zucker. Du wirst printf keine neuen Format-Spezifikatoren beibringen können, und in C89 wirst du einen Aufruf der Form printf("%s\n", prn_i128(x)); auch nicht kriegen. Für C++ und C99 habe ich dir bereits Code gegeben.

    Der dynamische Ansatz ist hier nicht wirklich sinnvoll - wenn du den syntaktischen Zucker aufweichst und einen weiteren Parameter mitgibst, um den Zeiger aufzunehmen und nachher freizugeben, kannst du genau so gut einen Zeiger auf einen Buffer auf dem Stack mitgeben. Mehr als das ist wohl nicht drin.



  • Deine Lösung ist ja auch nicht schlecht, ganz im Gegenteil. Aber sie lässt sich bei mir mit "-std=c++0x" einfach nicht übersetzen und zweigleißig was Compiler- sowie Compiler-Optionen betrifft, wollte ich dann doch nicht fahren.
    Wenn Du mir noch sagen könntest, wie man Deine letzte Lösung auch im C++0x-Mode übersetzen und nutzen könnte, wärs ja perfekt.

    Ebenso wüsste ich gerne, wie ich meine Lösung statisch gestalten kann, ohne das man für jeden Aufruf ein extra char-Array benötigt.

    Mit "funktioniert tadellos" bezog ich mich ausschließlich auf die Ausgabe und die funktioniert nunmal tadellos, egal welche Werte ich mitgebe. Ich würde nur gerne die dynamisch erzeugten char-Array´s (p´s) wieder freigeben lassen. Nur wie?



  • Komm von printf weg, oder lebe mit den Einschränkungen.



  • 314159265358979 schrieb:

    Komm von printf weg, oder lebe mit den Einschränkungen.

    Wie oft denn noch? Habe ich einen C++-fähigen Compiler, nehme ich std::cout, keine Frage.

    std::cout oder andere C++-Elemente funktionieren nunmal aber nicht bei reiner C-Anwendung.

    Wie dem auch sei. Wenn jemand noch weiter weiß, kann er/sie es ja gerne hier posten. Ebenso wäre ich sehr dankbar für Vereinfachungen und Optimierungen meiner dynamisch gestalteten Lösung. Besser eine, als keine.

    Es geht ja auch darum, die Grenzen des "Möglichen" neu zu entdecken.



  • Schau auf Seite 4 dieses Threads, dritter Beitrag von unten; das kriegst du auch durch einen C++-Compiler. Danach halt

    #ifdef __cplusplus
    // C++-Code
    #else
    // C-Code
    #endif
    

    ...und in Dreckiger-Hack-Land ist alles wieder in Butter.

    Dass du C99-Code durch einen C++-Compiler nicht durchjagen kannst, ist nicht weiter verwunderlich - schließlich handelt es sich bei C und C++ um verschiedene Sprachen, und wo C++98 von C89 noch viel übernommen hat, ist das bei C99 nicht der Fall.



  • Schlitzauge schrieb:

    Wie oft denn noch? Habe ich einen C++-fähigen Compiler, nehme ich std::cout, keine Frage.

    Was du nicht sagst.

    Schlitzauge schrieb:

    std::cout oder andere C++-Elemente funktionieren nunmal aber nicht bei reiner C-Anwendung.

    Dann lebe mit den Einschränkungen.

    Schlitzauge schrieb:

    Wie dem auch sei. Wenn jemand noch weiter weiß, kann er/sie es ja gerne hier posten. Ebenso wäre ich sehr dankbar für Vereinfachungen und Optimierungen meiner dynamisch gestalteten Lösung. Besser eine, als keine.

    seldon hat dir bereits geholfen so gut es geht. Einerseits möchtest du eine C-printf Lösung, andererseits soll es mit C++0x kompilierbar sein. Das ergibt keinen Sinn.

    Schlitzauge schrieb:

    Es geht ja auch darum, die Grenzen des "Möglichen" neu zu entdecken.

    Da gibts nix neu zu entdecken, wir können programmieren. Die bestmöglichen Lösungen hast du bekommen, es _geht_ nicht besser.

    Und ganz ehrlich gesagt bezweifle ich bei deinen Kenntnissen auch mal stark, dass du den Typen brauchst.

    @seldon: Selbe Sekunde, nice 😉



  • Es geht ja auch darum, die Grenzen des "Möglichen" neu zu entdecken.

    Wie willst du die Implementation einer Funktion wie printf aendern, wenn du keinen Zugriff auf den Quellcode hast? Ich verstehe dein Anliegen in keinster Weise. Der andere Punkt: Wenn es dir um die Grenzen des Moeglichen geht, dann lote sie selbst aus. Was brauchst du uns dazu?



  • seldon schrieb:

    Schau auf Seite 4 dieses Threads, dritter Beitrag von unten; das kriegst du auch durch einen C++-Compiler.

    An #ifdef __cplusplus hatte ich in der Tat auch schon gedacht, würde ich letztendlich vlt. sogar machen. Das wäre für mich aber erst zweite Wahl gewesen. Ich fand bzw. finde es noch sehr reizvoll, dass codeseitig mit eigener[n] Funktion(en) zu realisieren, denn das scheint ja doch nicht allzu einfach zu sein, wenn es denn möglich sein sollte.
    Aber bzgl. des dritten Beitrags von unten auf Seite 4:
    Warum sollte das auch nicht gehen? Ist doch eine C++-Lösung oder etwa nicht?
    Oder haste Dich einfach in der Seite und/oder Beitrag geirrt?

    314159265358979 schrieb:

    Schlitzauge schrieb:

    Wie oft denn noch? Habe ich einen C++-fähigen Compiler, nehme ich std::cout, keine Frage.

    Was du nicht sagst.

    Doch doch, oft genug. Es ist ja auch kein Ding, einfach std::cout zu verwenden, C++-fähigen Compiler vorausgesetzt, versteht sich.
    Es kommt leider aber auch mal vor, dass ich an PC´s sitze, wo es nur C-Compiler gibt und ich "mit den Einschränkungen nunmal leben muss".

    314159265358979 schrieb:

    Dann lebe mit den Einschränkungen.

    Es ist für mich kein MustHave, sondern reine Interessenfrage. 😉

    314159265358979 schrieb:

    seldon hat dir bereits geholfen so gut es geht. Einerseits möchtest du eine C-printf Lösung, andererseits soll es mit C++0x kompilierbar sein. Das ergibt keinen Sinn.

    Nicht nur er, jeder hier. Deshalb nochmal großen THX an alle.
    Aber Du irrst, es ergibt schon einen Sinn. Bei Lösungen für Beides ist es dann egal, ob man in C++ oder reinem ANSI-C schreibt.
    Zur Not schreibe ich mir halt eine printf_[u]i128()-Funktion, die selbst inline printf() für jedes extrahiertes Zeichen für jeweils eine Ausgabe verwendet. GMP geht ja ähnlich vor.
    Ebenso könnte ich auch die bisherige statische C-Lösung verwenden. Müsste dann halt nur jede __[u]int128_t-Ausgabe mit printf() einzeln tätigen, denn das funktioniert ja, nur mehrfach nicht.
    Und wenn C++-Compiler vorhanden, verwende ich einfach std::cout bei printf(), wenn ich mit C++-Compiler hier und dort ANSI-C verwenden möchte. Lösungen dafür konnte ich breits implementieren.

    314159265358979 schrieb:

    Da gibts nix neu zu entdecken, wir können programmieren. Die bestmöglichen Lösungen hast du bekommen

    Habe auch nie etwas anderes behauptet oder gedacht. Ich respektiere schon Eure(r) Meinungen, Wissen und Können.

    314159265358979 schrieb:

    Und ganz ehrlich gesagt bezweifle ich bei deinen Kenntnissen auch mal stark, dass du den Typen brauchst.

    Das ich natürlich nicht alles kann, ist gewiss, wäre ja auch langweilig schon alles zu wissen bzw. zu können. Wo bleibt da der Spaß und Reiz?
    Betrachtet es halt wie ich: als [kleine] Herausforderung das vermeintlich Unlösbare, doch irgendwie lösbar zu machen (Soll jetzt kein Befehl oder Dergleichen sein. Es steht natürlich jedem frei!).
    Doch Du irrst wieder. Ich brauche sehr wohl solch große Zahlenbereiche solchen Typs, da ich Anwendungen für Astrophysik und Kernphysik schreibe.

    --------------------
    Naja, wie dem auch sei. Ich glaube mit einer C-Lösung unter gegebenen Bedingungen, die ich mir stelle, kommen wir hier wohl nicht mehr weiter. Es sollte ja auch nur was Optionales sein. Hätte trotzdem noch jemand Lösungen / Lösungsvorschläge parat, bitte POSTEN! THX!

    Eines wäre trotzdem noch super. Könnte jemand mal über meine dynamisch gestaltete Lösung schauen. Ich hatte da noch drei Kritikpunkte (Seite 6, letzter Beitrag), u.a. wie ich den allokierten Speicher wieder freigeben könnte (z.B. mit free()) oder auch, was mir wichtiger ist, wie man dort manches vereinfachen könnte.
    Oder könnte man meine Lösung irgendwie auch statisch gestalten? An der Art der Bedienung sollte sich dabei natürlich nichts ändern, wenn möglich.

    Ich wollte mich auch nicht allzu lange damit aufhalten, da ich im Moment eh an einem Rechner mit C++-Compilern sitze, was auch für die nächste Zeit gilt. Außerdem befinden wir uns hier im C++-Abteil, nicht für C.

    Deshalb wieder zu meinem ursprünglichen Anliegen. Einige C++-Lösungen konnte ich erfolgreich implementieren und funktionieren wunderbar. Einige jedoch nicht, da der Compiler etwas auszusetzen hat. Diese Meldungen kann ich allerdings übrhaupt nicht deuten.

    C++-Lösung 1:

    const char* INT128ToCSTR3(__int128_t x,std::vector<char>& buffer)
    {
      std::stringstream sstr;
      sstr<<x;
      buffer[sstr.str().copy(buffer,buffer.size()-1,0)] = 0;
      return &buffer[0];
    }
    
    const char* UINT128ToCSTR3(__uint128_t x,std::vector<char>& buffer)
    {
      std::stringstream sstr;
      sstr<<x;
      buffer[sstr.str().copy(buffer,buffer.size()-1,0)] = 0;
      return &buffer[0];
    }
    

    Compiler-Output zu C++-Lösung 1:

    sizeofs_main.cpp: In function ‘const char* INT128ToCSTR3(__int128_t, std::vector<char, std::allocator<char> >&)’:
    sizeofs_main.cpp:123: error: no matching function for call to ‘std::basic_string<char, std::char_traits<char>, std::allocator<char> >::copy(std::vector<char, std::allocator<char> >&, size_t, int)’
    /usr/lib/gcc/x86_64-redhat-linux/4.4.5/../../../../include/c++/4.4.5/bits/basic_string.h:1592: note: candidates are: typename std::basic_string<_CharT, _Traits, _Alloc>::size_type std::basic_string<_CharT, _Traits, _Alloc>::copy(_CharT*, typename _Alloc::rebind<_CharT>::other::size_type, typename _Alloc::rebind<_CharT>::other::size_type) const [with _CharT = char, _Traits = std::char_traits<char>, _Alloc = std::allocator<char>]
    sizeofs_main.cpp: In function ‘const char* UINT128ToCSTR3(__uint128_t, std::vector<char, std::allocator<char> >&)’:
    sizeofs_main.cpp:131: error: no matching function for call to ‘std::basic_string<char, std::char_traits<char>, std::allocator<char> >::copy(std::vector<char, std::allocator<char> >&, size_t, int)’
    /usr/lib/gcc/x86_64-redhat-linux/4.4.5/../../../../include/c++/4.4.5/bits/basic_string.h:1592: note: candidates are: typename std::basic_string<_CharT, _Traits, _Alloc>::size_type std::basic_string<_CharT, _Traits, _Alloc>::copy(_CharT*, typename _Alloc::rebind<_CharT>::other::size_type, typename _Alloc::rebind<_CharT>::other::size_type) const [with _CharT = char, _Traits = std::char_traits<char>, _Alloc = std::allocator<char>]
    

    Das wäre die eine gewesen. Jetzt noch die zweite:

    C++-Lösung 2:

    template<std::size_t BuffSize>
    const char* INT128ToCSTR4(__int128_t x,std::array<char,BuffSize>& buffer)
    {
      std::stringstream sstr;
      sstr<<x;
      buffer[sstr.str().copy(buffer,buffer.size()-1,0)] = 0;
      return &buffer[0];
    }
    
    template<std::size_t BuffSize>
    const char* UINT128ToCSTR4(__uint128_t x,std::array<char,BuffSize>& buffer)
    {
      std::stringstream sstr;
      sstr<<x;
      buffer[sstr.str().copy(buffer,buffer.size()-1,0)] = 0;
      return &buffer[0];
    }
    

    Übersetzen lässt sie sich. Ich weiß nur nicht so recht, wie man diese dann anwendet.

    Folgendes scheint anscheinend nicht zu funktionieren:

    //char buffer3[41] = {NULL};
      std::array<char,41> buffer3/* = {NULL}*/;
      printf("%s\n",INT128ToCSTR4(2048,buffer3));
    

    Auch nicht, wenn ich ein klassisches Array verwende (Zeile 1).
    Nebenbei: wie kann ich alle Elemente eines std::array´s mit NULL initialisieren?

    Grüße

    Schlitzauge 🙂

    EDIT:

    knivil schrieb:

    Wie willst du die Implementation einer Funktion wie printf aendern, wenn du keinen Zugriff auf den Quellcode hast? Ich verstehe dein Anliegen in keinster Weise. Der andere Punkt: Wenn es dir um die Grenzen des Moeglichen geht, dann lote sie selbst aus. Was brauchst du uns dazu?

    Nein nein. printf() möchte ich so garnicht neu implementieren. Hab mich damit abgefunden, dass printf() keine neuen Typen direkt schluckt, sondern dass man dazu ne Funktion drumherumschreiben muss, welche anschließend ein printf()-fähiges Format liefert. Ich bin schon seit Wochen dabei "die Grenzen" selber auszuloten. Doch a.) weiß und kann ich nicht alles, b.) mehrere Augen sehen bzw. können mehr und c.) COMMUNITY-Gedanke halt (ist schließlich ein Forum).



  • Schlitzauge schrieb:

    Doch Du irrst wieder. Ich brauche sehr wohl solch große Zahlenbereiche solchen Typs, da ich Anwendungen für Astrophysik und Kernphysik schreibe.

    Mit int64_t kann ich Zahlen bis ±9223372036854775807 speichern. Mit double kann ich auf keine Ahnung wie viele Kommastellen genau Zahlen speichern, die wohl bis 10e300 oder so rauf gehen. Ich kann mir nicht vorstellen, dass das nicht ausreicht. Wenns wirklich so ist, kann man bestimmt was am Algortihmus umstellen, und wenns dann immer noch nicht reicht, dann nimm eine Library wie GMP dafür.



  • Naja, wenn man sich im Bereich der Astrophysik begibt - es gibt schwarze Löcher mit einer Masse von 1040 kg. Ob man die jetzt aufs Gramm genau braucht (oder kriegt) ist natürlich eine andere Frage.

    Double arbeitet mit einer Mantisse von 53 binären Stellen, was knapp 16 Dezimalstellen bedeutet (log10(253) ≈ 15,95), aber je nach Anwendungsfall kann es durchaus sein, dass Fließkommaberechnung weit weniger genaue Ergebnisse liefert - Differenzen zwischen sehr ähnlichen Werten, wie sie in der Elementarphysik durchaus auftreten können, säbeln dir, wenn du nicht aufpasst (und oft auch dann) viele Stellen Genauigkeit einfach weg. Es ist schon vorstellbar, dass man mit Fixed-Point-Arithmetik auf einem 128-Bit-Integer besser dran sein kann. Ggf. würde ich mich aber mit MP-Bibliotheken vertraut machen, denn wenn ich damit rechnen muss, einen 128-Bit-Integer auszureizen, würde ich auch damit rechnen, noch darüber hinaus gehen zu müssen.



  • Gibt natürlich auch noch long double, da sollten sich noch ein paar Stellen gewinnen lassen.



  • struct int_buffer
    {
       char arr[64];
       char *p;
    };
    
    #define int128(x) int128_2_str(x).p
    
    int_buffer int128_2_str(__int128_t x)
    {
       struct int_buffer buffer; /* muss man das in C noch so schreiben ? */
       buffer.p = buffer.arr + 63; 
       *(buffer.p) = '\0';
       --(buffer.p);
       /* jetzt arbeitest du mit dem buffer.p weiter */
    
       /* hier kommt dein code, wie gehabt */
    
       return buffer;
    }
    
    printf("%s", int128(123123232123321));
    

    damit sollte das buffer problem geloest sein

    Meep Meep


  • Mod

    Meep Meep schrieb:

    damit sollte das buffer problem geloest sein

    Das hatten wir schon. Und wenn das eine Lösung für C sein soll: das ist undefiniert. C kennt keine temporärem Objekte.



  • camper schrieb:

    Und wenn das eine Lösung für C sein soll: das ist undefiniert. C kennt keine temporärem Objekte.

    oh. das wusste ich nicht

    das das bufferproblem geloest wurde, hab ich scheinbar ueberlesen


Anmelden zum Antworten