C++ 中有 128 位整数吗?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/18439520/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Is there a 128 bit integer in C++?
提问by danijar
I need to store a 128 bits long UUIDin 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.
我需要在一个变量中存储一个 128 位长的UUID。C++ 中有 128 位数据类型吗?我不需要算术运算,我只想快速轻松地存储和读取值。
A new feature from C++11 would be fine, too.
C++11 的新特性也不错。
采纳答案by doron
GCC and Clang support __int128
GCC 和 Clang 支持 __int128
回答by Onkar
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.
尽管 GCC 确实提供了__int128
,但仅支持具有足以容纳 128 位的整数模式的目标(处理器)。在给定的系统上,sizeof()intmax_t
并uintmax_t
确定编译器和平台支持的最大值。
回答by Patrik Beck
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.
这比字符串和数组要好,尤其是当您需要用它进行算术运算时。
回答by ST3
Your question has two parts.
你的问题有两个部分。
1.128-bin
integer. As suggested by @PatrikBeck boost::multiprecision
is good way for really big integers.
1.128-bin
整数。正如@PatrikBeck 所建议的boost::multiprecision
那样,对于真正的大整数来说是个好方法。
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 structurewhich is designed for that purpose. As cross-platform tag added, you can simply copy that structure to your code and make it like:
2.Variable to store UUID
/ GUID
/ CLSID
or what you call it. 在这种情况下boost::multiprecision
不是一个好主意。您需要为此目的而设计的GUID 结构。随着跨平台标签的添加,您可以简单地将该结构复制到您的代码中并使其如下所示:
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.
使用简单的结构而不是可以处理一堆不同东西的对象,您将获得更好的性能。无论如何,您不需要使用 GUIDS 进行数学运算,因此您不需要任何花哨的对象。
回答by Cale McCollough
There is no 128-bit integer in Visual-C++ because the Microsoft calling convention only allows returning of 2 32-bit values in the RAX:EAX pair. The presents a constant headache because when you multiply two integers together with the result is a two-word integer. Most load-and-store machines support working with two CPU word-sized integers but working with 4 requires software hack, so a 32-bit CPU cannot process 128-bit integers and 8-bit and 16-bit CPUs can't do 64-bit integers without a rather costly software hack. 64-bit CPUs can and regularly do work with 128-bit because if you multiply two 64-bit integers you get a 128-bit integer so GCC version 4.6 does support 128-bit integers. This presents a problem with writing portable code because you have to do an ugly hack where you return one 64-bit word in the return register and you pass the other in using a reference. For example, in order to print a floating-point number fast with Grisuwe use 128-bit unsigned multiplication as follows:
Visual-C++ 中没有 128 位整数,因为 Microsoft 调用约定只允许返回 RAX:EAX 对中的 2 个 32 位值。这会让人头疼不已,因为当你将两个整数相乘时,结果是一个两个字的整数。大多数加载和存储机器支持使用两个 CPU 字大小的整数,但使用 4 需要软件破解,因此 32 位 CPU 不能处理 128 位整数,8 位和 16 位 CPU 不能处理 64 -bit 整数,没有相当昂贵的软件黑客。64 位 CPU 可以并且经常使用 128 位,因为如果将两个 64 位整数相乘,您会得到一个 128 位整数,因此 GCC 4.6 版确实支持 128 位整数。这给编写可移植代码带来了一个问题,因为你必须做一个丑陋的黑客攻击,在返回寄存器中返回一个 64 位字,然后使用引用传递另一个。例如,为了快速打印浮点数Grisu我们使用 128 位无符号乘法如下:
#include <cstdint>
#if defined(_MSC_VER) && defined(_M_AMD64)
#define USING_VISUAL_CPP_X64 1
#include <intrin.h>
#include <intrin0.h>
#pragma intrinsic(_umul128)
#elif (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 6))
#define USING_GCC 1
#if defined(__x86_64__)
#define COMPILER_SUPPORTS_128_BIT_INTEGERS 1
#endif
#endif
#if USING_VISUAL_CPP_X64
UI8 h;
UI8 l = _umul128(f, rhs_f, &h);
if (l & (UI8(1) << 63)) // rounding
h++;
return TBinary(h, e + rhs_e + 64);
#elif USING_GCC
UIH p = static_cast<UIH>(f) * static_cast<UIH>(rhs_f);
UI8 h = p >> 64;
UI8 l = static_cast<UI8>(p);
if (l & (UI8(1) << 63)) // rounding
h++;
return TBinary(h, e + rhs_e + 64);
#else
const UI8 M32 = 0xFFFFFFFF;
const UI8 a = f >> 32;
const UI8 b = f & M32;
const UI8 c = rhs_f >> 32;
const UI8 d = rhs_f & M32;
const UI8 ac = a * c;
const UI8 bc = b * c;
const UI8 ad = a * d;
const UI8 bd = b * d;
UI8 tmp = (bd >> 32) + (ad & M32) + (bc & M32);
tmp += 1U << 31; /// mult_round
return TBinary(ac + (ad >> 32) + (bc >> 32) + (tmp >> 32), e + rhs_e + 64);
#endif
}
回答by Silanus
use the TBigInteger template and set any bit range in the template array like this TBigInt<128,true> for being a signed 128 bit integer or TBigInt<128,false> for being an unsigned 128 bit integer. Hope that helps maybe a late reply and someone else found this method already.
使用 TBigInteger 模板并在模板数组中设置任何位范围,如 TBigInt<128,true> 为有符号 128 位整数或 TBigInt<128,false> 为无符号 128 位整数。希望这有助于可能是迟到的回复,而其他人已经找到了这种方法。
回答by Mikhail Vasilyev
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.
我建议使用std::bitset<128>
(你总是可以做类似的事情using UUID = std::bitset<128>;
)。它可能具有与其他答案中提出的自定义结构类似的内存布局,但您不需要定义自己的比较运算符、哈希等。