Is there a 128 bit integer in C++?
Solution 1
GCC and Clang support __int128
Solution 2
Although GCC does provide __int128
, it is supported only for targets (processors) which have an integer mode wide enough to hold 128 bits. On a given system, sizeof() intmax_t
and uintmax_t
determine the maximum value that the compiler and the platform support.
Solution 3
Checkout boost's implementation:
#include <boost/multiprecision/cpp_int.hpp>
using namespace boost::multiprecision;
int128_t v = 1;
This is better than strings and arrays, especially if you need to do arithmetic operations with it.
Solution 4
Your question has two parts.
1.128-bit
integer. As suggested by @PatrikBeck boost::multiprecision
is good way for really big integers.
2.Variable to store UUID
/ GUID
/ CLSID
or whatever you call it. In this case boost::multiprecision
is not a good idea. You need GUID structure which is designed for that purpose. As cross-platform tag added, you can simply copy that structure to your code and make it like:
struct GUID
{
uint32_t Data1;
uint16_t Data2;
uint16_t Data3;
uint8_t Data4[8];
};
This format is defined by Microsoft because of some inner reasons, you can even simplify it to:
struct GUID
{
uint8_t Data[16];
};
You will get better performance having simple structure rather than object that can handle bunch of different stuff. Anyway you don't need to do math with GUIDS, so you don't need any fancy object.
Solution 5
I would recommend using std::bitset<128>
(you can always do something like using UUID = std::bitset<128>;
). It will probably have a similar memory layout to the custom struct proposed in the other answers, but you won't need to define your own comparison operators, hash etc.
danijar
Researcher aiming to build intelligent machines based on concepts of the human brain. Website · Twitter · Scholar · Github
Updated on January 27, 2022Comments
-
danijar over 2 years
I need to store a 128 bits long UUID in a variable. Is there a 128-bit datatype in C++? I do not need arithmetic operations, I just want to easily store and read the value very fast.
A new feature from C++11 would be fine, too.
-
Jesse Good over 10 yearsBoost also has a uuid library btw.
-
danijar over 10 years@JesseGood I may use that library, but I'd like store the ids in a standard type.
-
Kurt Pattyn over 10 yearsRegarding boost, you can also have a look at this post: stackoverflow.com/a/16218841/52568
-
Jesse Good over 10 years@danijar: What "standard"?
boost
usesuint8_t data[16];
whilelibuuid
isunsigned char data[16];
, all libraries I know use arrays. -
danijar over 10 years@JesseGood Okay, I didn't knew that. Then this is fine. The only challenge might be to use it as key in an
std::unordered_map
. I am not sure if arrays can be used without providing my own hash function. -
Jesse Good over 10 years@danijar: That's not too difficult, see the answer here.
-
James Kanze over 10 years@JesseGood Curious as to why they would use
uint8_t
. There are only two operations (other than copy and assignment) which make sense on a UUID: comparison for equality, and conversion to a string. The larger the basic type, the faster the comparison (up to a point), and the string format of the UUID suggestsuint16_t
. Souint16_t
or larger would seem to be in order. -
Jesse Good over 10 years@JamesKanze: I'm not 100 percent sure, but byte-ordering would be a factor since uuids are often used in network messaging.
-
James Kanze over 10 years@JesseGood Good point. That probably explains it. (In all of the cases where I've used UUID, they've ended up in text files, so the byte order has been irrelevant.)
-
MFH over 10 years@JamesKanze: The type of storage should be negligible as UUIDs are fixed size and can therefor be compared via
std::memcmp
. (assuming that the byte-order of both UUIDs is equal [which it should be anyways]) -
James Kanze over 10 years@MFH But
memcmp
will probably be less than optimal for the comparison. (Whether that's relevant or not is another question.) -
MFH over 10 years@JamesKanze: I'd say that's a question of implementation. There is nothing preventing a 100% standard compatible version to reinterpret the pointers as
const unsigned long long
whencount == 2 * sizeof(unsigned long long)
. If it does that than it will actually be able to compare both UUIDs with 4 read operations and 2 compares. But even if it doesn't do that it will still very likely be extremely fast due to caching. -
CppNoob over 8 yearsUpvoted because it points out an issue with the accepted answer.
-
Peter Cordes about 8 yearsThis isn't quite correct:
__int128_t
is supported on x86-64 (but not i386). It's implemented in 64bit integer registers using addition-with-carry, and extended-precision code for shifts, multiplies, and so on. (The 128b SSE vector registers aren't useful for anything except boolean (AND/OR/XOR), because they can't do a single 128b add. SSE can do two 64b adds, or multiple smaller elements). -
user3342339 about 8 yearsonly for 64-bit architectures, though. See gcc.gnu.org/onlinedocs/gcc/_005f_005fint128.html
-
user1418199 about 8 yearsboost::multiprecision::int128_t seems to have performance issues compared against __int128_t. {code} #include "vlib/stopwatch.hpp" #include <iostream> #include <string> #include <boost/multiprecision/cpp_int.hpp> using namespace std; int main(int , char **argv) { size_t cnt = std::stoull(argv[1]); __int128_t counter = 0; for(size_t i = 0; i < cnt; ++i) { ++counter; counter <<= 2; } } {code} boost takes 20x the time on this code.
-
HolyBlackCat over 5 yearsThere is no such template in the standard library. What library are you talking about?
-
Admin over 4 yearsNon 64-bit desktops are very rare and if your arduino would totally ever need 128bits to store a single value that's a different topic. @user3342339
-
einpoklum about 4 yearsIs there a preprocessor define such as
HAVE_INT_128_T
or something similar we could check? -
phuclv about 4 yearsthe pair is EDX:EAX or RDX:RAX. There's no RAX:EAX pair.