Zum Inhalt springen

Fragen zu 128-Bit Integer


DITTY

Empfohlene Beiträge

Hallo COM,

System: Linux x64-86

ich probiere mich gerade an einigen Datentypen, u.a. dem GCC bekannten

"__int128_t" und "__uint128_t".

Übersetzen lassen sich diese und auch das Rechnen funktioniert wunderbar.

Ich habe aber gerade ein Problem mit der Ausgabe via printf(,) und std::cout.

1.) printf(,):

Ich weiß von anderen Datentypen wie "__int64_t", dass es zumindest für printf(,) spezielle PRI-Makros für solche Datentypen gibt:

Galileo Computing :: C von A bis Z – B.7 <inttypes.h> (C99)

Folgende Aufrufe funktionieren:

printf("x: %"PRIi64"\n",Variable)";

printf("x: %"PRIu64"\n",Variable)";
Doch für die __int128_t-Datentypen irgendwie nicht. Folgendes funktioniert nicht (Compiler-Fehler):
printf("x: %"PRIi128"\n",Variable)";

printf("x: %"PRIu128"\n",Variable)";
Compiler-Aufruf:
g++ -std=c++0x -m64 -fopenmp -Wall -Wextra -pedantic -pedantic-errors -O3 -s sizeofs_main.cpp -o sizeofs_main
Compiler-Output:
sizeofs_main.cpp:84: error: expected ‘)’ before ‘PRIu128’

sizeofs_main.cpp:84: warning: spurious trailing ‘%’ in format

sizeofs_main.cpp:84: warning: too many arguments for format
Da es die beiden Datentypen:
__int128_t

__uint128_t
aber gibt, frage ich mich nun, wie das Makro hierfür heißen muss? 2.) std::cout: Ebenso würde ich gerne wissen, wie ich das mit std:cout ausgeben kann. Mit:
__int128_t Var1 = 1024;

cout << Var1 << endl;
funktionierts zumindest nicht. Compiler-Output:
sizeofs_main.cpp:84: error: ambiguous overload for ‘operator<<’ in ‘std::cout << Var31’

/usr/lib/gcc/x86_64-redhat-linux/4.4.5/../../../../include/c++/4.4.5/ostream:165: note: candidates are: std::basic_ostream<_CharT, _Traits>& std::basic_ostream<_CharT, _Traits>::operator<<(long int) [with _CharT = char, _Traits = std::char_traits<char>]

/usr/lib/gcc/x86_64-redhat-linux/4.4.5/../../../../include/c++/4.4.5/ostream:169: note:                 std::basic_ostream<_CharT, _Traits>& std::basic_ostream<_CharT, _Traits>::operator<<(long unsigned int) [with _CharT = char, _Traits = std::char_traits<char>]

/usr/lib/gcc/x86_64-redhat-linux/4.4.5/../../../../include/c++/4.4.5/ostream:173: note:                 std::basic_ostream<_CharT, _Traits>& std::basic_ostream<_CharT, _Traits>::operator<<(bool) [with _CharT = char, _Traits = std::char_traits<char>]

/usr/lib/gcc/x86_64-redhat-linux/4.4.5/../../../../include/c++/4.4.5/bits/ostream.tcc:91: note:                 std::basic_ostream<_CharT, _Traits>& std::basic_ostream<_CharT, _Traits>::operator<<(short int) [with _CharT = char, _Traits = std::char_traits<char>]

/usr/lib/gcc/x86_64-redhat-linux/4.4.5/../../../../include/c++/4.4.5/ostream:180: note:                 std::basic_ostream<_CharT, _Traits>& std::basic_ostream<_CharT, _Traits>::operator<<(short unsigned int) [with _CharT = char, _Traits = std::char_traits<char>]

/usr/lib/gcc/x86_64-redhat-linux/4.4.5/../../../../include/c++/4.4.5/bits/ostream.tcc:105: note:                 std::basic_ostream<_CharT, _Traits>& std::basic_ostream<_CharT, _Traits>::operator<<(int) [with _CharT = char, _Traits = std::char_traits<char>]

/usr/lib/gcc/x86_64-redhat-linux/4.4.5/../../../../include/c++/4.4.5/ostream:191: note:                 std::basic_ostream<_CharT, _Traits>& std::basic_ostream<_CharT, _Traits>::operator<<(unsigned int) [with _CharT = char, _Traits = std::char_traits<char>]

/usr/lib/gcc/x86_64-redhat-linux/4.4.5/../../../../include/c++/4.4.5/ostream:200: note:                 std::basic_ostream<_CharT, _Traits>& std::basic_ostream<_CharT, _Traits>::operator<<(long long int) [with _CharT = char, _Traits = std::char_traits<char>]

/usr/lib/gcc/x86_64-redhat-linux/4.4.5/../../../../include/c++/4.4.5/ostream:204: note:                 std::basic_ostream<_CharT, _Traits>& std::basic_ostream<_CharT, _Traits>::operator<<(long long unsigned int) [with _CharT = char, _Traits = std::char_traits<char>]

/usr/lib/gcc/x86_64-redhat-linux/4.4.5/../../../../include/c++/4.4.5/ostream:209: note:                 std::basic_ostream<_CharT, _Traits>& std::basic_ostream<_CharT, _Traits>::operator<<(double) [with _CharT = char, _Traits = std::char_traits<char>]

/usr/lib/gcc/x86_64-redhat-linux/4.4.5/../../../../include/c++/4.4.5/ostream:213: note:                 std::basic_ostream<_CharT, _Traits>& std::basic_ostream<_CharT, _Traits>::operator<<(float) [with _CharT = char, _Traits = std::char_traits<char>]

/usr/lib/gcc/x86_64-redhat-linux/4.4.5/../../../../include/c++/4.4.5/ostream:221: note:                 std::basic_ostream<_CharT, _Traits>& std::basic_ostream<_CharT, _Traits>::operator<<(long double) [with _CharT = char, _Traits = std::char_traits<char>]

/usr/lib/gcc/x86_64-redhat-linux/4.4.5/../../../../include/c++/4.4.5/ostream:451: note:                 std::basic_ostream<_CharT, _Traits>& std::operator<<(std::basic_ostream<_CharT, _Traits>&, char) [with _CharT = char, _Traits = std::char_traits<char>]

/usr/lib/gcc/x86_64-redhat-linux/4.4.5/../../../../include/c++/4.4.5/ostream:457: note:                 std::basic_ostream<char, _Traits>& std::operator<<(std::basic_ostream<char, _Traits>&, char) [with _Traits = std::char_traits<char>]

/usr/lib/gcc/x86_64-redhat-linux/4.4.5/../../../../include/c++/4.4.5/ostream:463: note:                 std::basic_ostream<char, _Traits>& std::operator<<(std::basic_ostream<char, _Traits>&, signed char) [with _Traits = std::char_traits<char>]

/usr/lib/gcc/x86_64-redhat-linux/4.4.5/../../../../include/c++/4.4.5/ostream:468: note:                 std::basic_ostream<char, _Traits>& std::operator<<(std::basic_ostream<char, _Traits>&, unsigned char) [with _Traits = std::char_traits<char>]
Bis einschließlich __uint64_t hingegen schon:
__uint64_t Var2 = 1024;

cout << Var2 << endl;

THX schonmal im Voraus!

Grüße

DITTY :):):):)

Link zu diesem Kommentar
Auf anderen Seiten teilen

Nein nein.

Syntax sollte richtig sein.

Um ehrlich zu sein, habe ich mich auch über diese Syntax gewundert.

Aber hier mal zum Vergleich mit __uint64_t:

__uint64_t test = 1024;

printf("x: %"PRIu64"\n",Var30);

printf("x: %PRIu64\n",Var30);

Output - Programm:
x: 1024

x: %PRIu64

Wie man sehen kann, funktionierts nur so mit printf().

Wie Anfangs aber erwähnt, geht das nur einschließlich bis zu den 64-Bit-Typen.

std:cout akzeptiert ebenfalls diese Datentypen, sogar ohne spezielle Syntax.

Lediglich bei den oben beiden genannten 128-Bit-Typen treten Anfangs beschriebene Probleme auf.

Grüße

Schlitzauge :)

Link zu diesem Kommentar
Auf anderen Seiten teilen

Es ist war lange her' date=' dass ich mit C++ gearbeitet habe, aber ich bin mir [u']sicher, dass die printf() so definitiv nicht aufgebaut wird.
Wenn das Makro durch ein Stringliteral ersetzt wird, passt das. Hintereinanderstehende Stringliterale werden einfach verbunden.

@DITTY:

Diese Datentypen sind nicht Bestandteil des Standards, sondern ein Zusatzfeature deines Compilers. Insofern solltest du deine Compilerdokumentation bemühen. Falls dein Compiler zwar mit dem 128-Bit-Typ rechnen, aber ihn (noch) nicht ausgeben kann, kannst du dir natürlich auch eine Ausgabefunktion selbst schreiben.

Bearbeitet von Klotzkopp
Link zu diesem Kommentar
Auf anderen Seiten teilen

Ich habe jetzt schon Stunden recherchiert und ja auch die Doku zu meinem Compiler durchforstet, ebenso zu den ganzen verwendeten Bilbtiotheken.

Mir ist schon klar, dass die 128-Bit-Datentypen derzeit kein Standard sind. Habe ich aber auch nie gedacht und behauptet. Sie müssen auch kein Standard sein. Sie stehen aber auf meinem System zur Verfügung und dort möchte ich sie auch gerne einsetzen.

Insofern ich keine Ausgaben damit machen möchte, funktioniert alles auch bestens.

Mir geht es jetzt aber darum diese 128-Bit-Datentypen auszugeben.

Und nein, ich plane nicht, extra hierfür einen eigenen 128-Bit-Datentyp zu schreiben. Natürlich bin ich selber auf die Idee gekommen und ich habe auch kein Problem damit sowas umzusetzen. Mir geht es aber EXPLIZIT um die beiden vom Compiler unterstützten Datentypen:

__int128_t

__uint128_t

und deren Ausgabemöglichkeiten mit printf(,), std::cout oder auch meinetwegen mit anderen Methoden.

Gerne würde ich auch eine eigene Methode zur Ausgabe dieser Datentypen schreiben, aber hab keinen blassen Schimmer wie. => Rückblende:

Ich bin ja auf der Suche nach Möglichkeiten, diese Datentypen auszugeben.

Wie, ist mir egal, solange sie auf meinem Screen landen.

Da es bereits ähnliche Datentypen, z.B.: __int64_t gibt, und printf(,) unter obenstehender Syntaxanwendung damit klar kommt, ebenso std::cout, sogar ohne spezieller Syntaxanwendung, wäre mir natürlich eine Lösung mit printf() und/oder std::cout am liebsten.

Wenn es etwas zur Ausgabe der 128-Bit-Typen in der Doku zu meinem Compiler oder in den Bibliotheken gibt, habe ich es nicht finden können. Deshalb suche ich ja Foren, wie dieses auf, mit der Hoffnung, dass mir Jemand Antworten / Lösungen auf das Problem geben kann.

Könnte ja sein, dass jemand etwas in der Doku oder im Internet findet, welches ich übersehen habe.

Oder vlt. hat schonmal jemand mit den genannten Datentypen gearbeitet.

Gibt es für printf(,) oder cout spezielle Makros für die 128-Bit-Datentypen? Alles, was ich im Internet gefunden hab, zeigt nur Lösungen bis einschließlich den 64-Bit-Datentypen, aber auch ich finde gewiss nicht immer alles im WWW. Deshalb => Forum bzw. Foren.

Grüße

DITTY :)

Link zu diesem Kommentar
Auf anderen Seiten teilen

Gerne würde ich auch eine eigene Methode zur Ausgabe dieser Datentypen schreiben, aber hab keinen blassen Schimmer wie.
Das ist doch eine Grundübung: Wiederholtes Dividieren durch 10 liefert dir als Divisionsrest die einzelnen Ziffern. Die musst du dann nur noch in umgekehrter Reihenfolge ausgeben. Das kannst du erreichen, indem du die Ziffern in einem Puffer sammelst, oder durch Rekursion.
Link zu diesem Kommentar
Auf anderen Seiten teilen

Irgendwie reden Wir Heute aneinander vorbei :).

Bin dennoch sehr dankbar für Eure Hilfen!!! (DAUMEN HOCH, gibts leider nicht als Smile => Anregung)

Das ist doch eine Grundübung: Wiederholtes Dividieren durch 10 liefert dir als Divisionsrest die einzelnen Ziffern. Die musst du dann nur noch in umgekehrter Reihenfolge ausgeben. Das kannst du erreichen, indem du die Ziffern in einem Puffer sammelst, oder durch Rekursion.

Stimmt. Na gut, klärt das Eine.

Ich würde gerne aber lieber mit printf(,) oder std:cout arbeiten wollen.

Ich kann mir beim besten Willen nicht vorstellen, dass die die Ausgabemöglichkeit vergessen haben, als se die 128-Bit-Integer implementiert haben.

Mit __int64_t funktionierts doch auch, dank Makro und std:cout unterstützt´s direkt.

Gibt es für printf() vlt. ein Makro für die genannten 128-Bit-Integer?

Wie gesagt, "long double" selbst mit 2^512 unterstützt´s ja auch. Ja gut, Standard. Aber wenn jemand so einen Datentyp wie __int128_t implementiert, muss er es doch auch mal ausgegeben haben.

Ich sehe in den Dokus nüscht. Kann da vlt. jemand mal schauen? Vlt. übersehe ich ja was Essentielles.

Auch wenn es OT ist, aber ich bei den meisten Problemen auch mathematischen Problemen reicht ein 64Bit Datentyp im Normalfall aus. Da der 128 Bittyp ja noch nicht im Standard ist, würde ich eigentlich darauf verzichten.

Ja, schon klar. Mir gehts rein vom Interesse aus.

Wie ich das mit 64-Bit-Integer handhabe, weiß ich ja, wie ich bereits geschrieben habe. Mir gehts aber EXPLIZIT um diese beiden implementierten 128-Bit-Integer.

THX und Grüße

DITTY :)

Bearbeitet von DITTY
Link zu diesem Kommentar
Auf anderen Seiten teilen

Ich würde gerne aber lieber mit printf(,) oder std:cout arbeiten wollen.
Für cout kannst du dir selbst einen Ausgabeoperator schreiben.

Ich kann mir beim besten Willen nicht vorstellen, dass die die Ausgabemöglichkeit vergessen haben, als se die 128-Bit-Integer implementiert haben.
Anscheinend ist das eine recht neue Erweiterung des GCC, und ist auch nur für 64-Bit-Plattformen verfügbar. Ich vermute, die Entwickler sind einfach noch nicht soweit, oder behandeln das mit niedriger Priorität. Eine Spezialisierung von std::numeric_limits gibt's dafür offenbar auch noch nicht. Bei diesen Datentypen stand vermutlich die Berechnung im Vordergrund, nicht die Ein- und Ausgabe als Text. Ein Mensch kann mit Zahlen dieser Größenordnung ohnehin nicht viel anfangen.

Aber wenn jemand so einen Datentyp wie __int128_t implementiert, muss er es doch auch mal ausgegeben haben.
Da wäre mir bei Open Source aber schon Eigenartigeres begegnet ;)

Ich sehe in den Dokus nüscht. Kann da vlt. jemand mal schauen? Vlt. übersehe ich ja was Essentielles.
Ich hab auf Anhieb auch nichts gefunden, nur ein paar Leute, die dasselbe Problem haben, aber auch da keine Antwort. Bearbeitet von Klotzkopp
Link zu diesem Kommentar
Auf anderen Seiten teilen

Habt großen Dank.

Habs soweit jetzt hinbekommen. Hier ein Bsp.-Prog. für std::cout:

INTS128.cpp:

#include <climits>

#include <cstdint>

#include <cinttypes>

#include <cfloat>

#include <cmath>

#include <cstdlib>

#include <cstdio>

#include <stdio.h>

#include <iostream>


using namespace std;


std::ostream &operator<<(std::ostream &out, __uint128_t x)

{

  if(x >= 10)

  {

    out << x / 10;

  }

  return out << static_cast<unsigned>(x % 10);

}


std::ostream &operator<<(std::ostream &out, __int128_t x)

{

  if(x < 0)

  {

    out << '-';

    x = -x;

  }

  return out << static_cast<__uint128_t>( x);

}


int main(int argc, char *argv[])

{

  __int128_t         Var31 = 0, tmp31 = 0;

  __uint128_t        Var32 = 0, tmp32 = 1;


  cout << "128-Bit Integer\n-----------------\n";


  __int128_t INT128_MIN = (-170141183460469231731.687303715884105728) * pow(10,18);

  __int128_t INT128_MAX = ( 170141183460469231731.687303715884105727) * pow(10,18);


  //cout << "Vermutet:\nINT128-MIN:" << INT128_MIN << "\nINT128-MAX: " << INT128_MAX << "\n\nBerechnet:\n";


  __int128_t TMP128 = 0;

  TMP128 = INT128_MAX + 1;                       // ergibt INT128-MIN

  cout << "INT128-MIN: " << TMP128 << "\n";      // Ausgabe von INT128-MIN

  TMP128 = INT128_MIN - 1;                       // ergibt INT128-MAX

  cout << "INT128-MAX:  " << TMP128 << "\n";     // Ausgabe von INT128-MAX


  __uint128_t UINT128_MAX = (340282366920938463463.374607431768211455) * pow(10,18);

  __uint128_t UINT128_MIN = 0/* * pow(10,18)*/;


  __uint128_t TMPu128 = 0;

  TMPu128 = UINT128_MAX + 1;                     // ergibt UINT128-MIN

  cout << "UINT128-MIN: " << TMPu128 << "\n";    // Ausgabe von UINT128-MIN

  TMPu128 = UINT128_MIN - 1;                     // ergibt UINT128-MAX

  cout << "UINT128-MAX: " << TMPu128 << "\n";    // Ausgabe von UINT128-MAX


  getchar();

  return 0;

}
OS: Linux x64-86 (bei mir Scientific Linux 6.1 x64 (up2date)) g++(GCC)-Version: g++ (GCC) 4.4.5 20110214 (Red Hat 4.4.5-6) Glibc: x86_x64 - v2.12-1.25.el6_1.3 Compile (release): g++ -std=c++0x -m64 -fopenmp -Wall -Wextra -pedantic -pedantic-errors -O3 -s source.cpp -o dest Output (exec):
128-Bit Integer

-----------------

INT128-MIN: -170141183460469231731687303715884105728

INT128-MAX:  170141183460469231731687303715884105727

UINT128-MIN: 0

UINT128-MAX: 340282366920938463463374607431768211455

-----------------------

Wüsste noch jemand, wie man auch printf(,) dies beibringen kann?

Und kann man und wenn ja wie, printf(,) weitere Makros beibringen?

Ich wüsste da zwar jetzt ne Möglichkeit einfach einen Output mittels std:cout in eine String- bzw. char[]-Variable zu stecken und diese fprint(,) zu übergeben, allerdings würde ich nur ungern printf(,) mit std::cout kreuzen wollen. Lieber wäre mir, wenn ich wahlweise mein überladenes std::cout oder printf(,) verwenden könnte, ohne dass das eine vom anderen abhängig ist.

THX im Voraus,

Grüße

DITTY :)

Bearbeitet von DITTY
Link zu diesem Kommentar
Auf anderen Seiten teilen

Wüsste noch jemand, wie man auch printf(,) dies beibringen kann?
Es ist leider nicht möglich, printf durch irgendwelche benutzerdefinierten Funktion beizubringen, wie es mit unbekannten Typen umgehen muss. Wenn die Implementierung deiner C-Standardbibliothek im Quellcode vorliegt, könntest du printf selbst ändern, aber damit müsstest du diese modifizierte Standardbibliothek mit deinem Programm verteilen.

Und kann man und wenn ja wie, printf(,) weitere Makros beibringen?
Printf kennt gar keine Makros. Dass in deinem Beispiel das Formatfeld für die 64-Bit-Typen durch ein Makro dargestellt wird, hat vermutlich nur den Grund, die Portierbarkeit zu erleichtern.
Link zu diesem Kommentar
Auf anderen Seiten teilen

Dein Kommentar

Du kannst jetzt schreiben und Dich später registrieren. Wenn Du ein Konto hast, melde Dich jetzt an, um unter Deinem Benutzernamen zu schreiben.

Gast
Auf dieses Thema antworten...

×   Du hast formatierten Text eingefügt.   Formatierung wiederherstellen

  Nur 75 Emojis sind erlaubt.

×   Dein Link wurde automatisch eingebettet.   Einbetten rückgängig machen und als Link darstellen

×   Dein vorheriger Inhalt wurde wiederhergestellt.   Editor leeren

×   Du kannst Bilder nicht direkt einfügen. Lade Bilder hoch oder lade sie von einer URL.

Fachinformatiker.de, 2024 by SE Internet Services

fidelogo_small.png

Schicke uns eine Nachricht!

Fachinformatiker.de ist die größte IT-Community
rund um Ausbildung, Job, Weiterbildung für IT-Fachkräfte.

Fachinformatiker.de App

Download on the App Store
Get it on Google Play

Kontakt

Hier werben?
Oder sende eine E-Mail an

Social media u. feeds

Jobboard für Fachinformatiker und IT-Fachkräfte

×
×
  • Neu erstellen...