C/C++ 中的二进制量
我们在C/C++中常常使用的二进制类型是 int ,然而 int 并不是一个准确的数据类型,在不同编译器上, int 的大小可能不同,int 只保证有最少为16位,最大可能为64位
在网络编程以及其他对整数大小和上限要求严格的地方,请避免使用 _int_ 或者 _long_ 这类数据类型
实际编程中常用的二进制类型
在实际编程中,我们常用的二进制数据类型有如下(当然也有与其配套的unsigned xxx_t)
int8_t
int16_t
int32_t
int64_t
他们分别占用 1,2,4,8 Byte
int128
偶然得知这个世界上竟然出现了 __int128_t 这种神奇的数据类型,不禁各处搜索了下,GCC Docs 6.8 中有如下说明:
As an extension the integer scalar type __int128 is supported for targets which have an integer mode wide enough to hold 128 bits. Simply write __int128 for a signed 128-bit integer, or unsigned __int128 for an unsigned 128-bit integer. There is no support in GCC for expressing an integer constant of type __int128 for targets with long long integer less than 128 bits wide. [1]
大概来说就是看上去gcc是支持 int128
和 unsigned int128
的,但是又没指明是否作为标准.
我们便在不同平台做了如下测试:
Debian x86_64 with gcc version 4.9.3 (Debian 4.9.3-3) -std=c++11
$ cat test.cpp
#include <iostream>
#include <cstdint>
using namespace std;
int main(){
cout << "intmax_t's size = " <<sizeof(intmax_t) << endl;
__int128 s = 0xFFFFFFFFFFFFFFFF;
s = s * s;
cout << "__int128's size = " << sizeof(s) << endl;
#ifdef _INT128_DEFINED
cout << "INT128 has been defined" << endl;
#else
cout << "INT128 hasn't been defined" << endl;
#endif
}
使用 $ g++ -o test test.cpp -std=c++11
编译成功,运行得到的结果却让我有点迷茫
$ ./test
intmax_t's size = 8
__int128's size = 16
INT128 hasn't been defined
奇怪的是
_INT128_DEFINED 这个宏并没有被定义,但是 __int128 这个数据类型却通过了编译,且却实占用了16Byte的内存空间(哪位朋友知道的邮件我)
我们要来确认下它是否保存了16Byte大小的数字(最高约为3.4*10^38)
#include <iostream>
#include <cstdint>
using namespace std;
void print_uint128(unsigned __int128 n){
if (n == 0) {
return;
}
print_uint128(n/10);
putchar(n%10+0x30);
}
int main(){
unsigned __int128 s = 0xFFFFFFFFFFFFFFFF;
s = s*s;
print_uint128(s);
cout << endl;
}
(部分代码引用自[2])
得到结果
340282366920938463426481119284349108225
__int128
确实保存了2的128次方大小的数据
Windows X86_64 with gcc 4.9.2 (i686-posix-dwarf-rev1, Built by MinGW-W64 project)
在MinGW上,事情变得比较奇怪了,我这里实验发现 _INT128_DEFINED
这个宏是被定义了的,然而却找不到任何类似于 __int128
int128_t
int128
之类的数据类型的存在
这里也就没法演示了
其他
- 在网上找到的许多文章都是使用的
int128_t
,但是在我Debian系统上并没有这种数据类型的定义,只存在__int128
和unsigned __int128
这两种数据类型 - 值得注意的是,我并没有直接
s = 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
, 而是s = 0xFFFFFFFFFFFFFFFF;s = s * s
因为在我实验中,直接赋值0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
只能得到__uint64_t
所能容纳的最大值__,这说明在编译器中对于__int128
的 支持尚不完全
结束语
- 据说这个支持在 GCC 44.4.6以后[3](待考证)就已经存在,不过希望大家多下去考证
- 如果能在 NOIP 上能用
__int128
这种二进制量的话,老师再也不用担心我的高精度题目了
参考资料
[1]how to print __uint128_t number using gcc?
[2]6.8 128-bit Integers
[3]int128 on Linux for Intel compiler