- gf25051 的博客
《咸鱼概要 · C++》关于int128
- @ 2026-5-20 16:04:31
前言:
输入输出实现代码
std::ostream& operator<<(std::ostream& os, __int128 n) {
if (n == 0) return os << '0';
std::string s;
bool negative = false;
if (n < 0) {
negative = true;
n = -n;
}
while (n > 0) {
s += '0' + (n % 10);
n /= 10;
}
if (negative) s += '-';
std::reverse(s.begin(), s.end());
return os << s;
}
std::istream& operator>>(std::istream& is, __int128& n) {
std::string s;
is >> s;
n = 0;
bool negative = false;
size_t start = 0;
if (s[0] == '-') {
negative = true;
start = 1;
}
for (size_t i = start; i < s.size(); ++i) {
n = n * 10 + (s[i] - '0');
}
if (negative) n = -n;
return is;
}
C++ __int128 完全详解
一、基本概念
__int128 是 GCC 和 Clang 编译器提供的非标准扩展类型,用于表示128位整数。
// 基本声明
__int128 a; // 有符号128位整数
unsigned __int128 b; // 无符号128位整数
二、数值范围
| 类型 | 最小值 | 最大值 | 十进制范围 |
|---|---|---|---|
__int128 |
-2^127 | 2^127-1 | 约 -1.7e38 ~ 1.7e38 |
unsigned __int128 |
0 | 2^128-1 | 0 ~ 约 3.4e38 |
// 边界值(需要计算)
// 2^127 = 170141183460469231731687303715884105728
// 2^127-1 = 170141183460469231731687303715884105727
三、支持的操作
__int128 a = 10, b = 3;
// ✅ 所有算术运算
__int128 sum = a + b; // 加法
__int128 diff = a - b; // 减法
__int128 prod = a * b; // 乘法
__int128 quot = a / b; // 除法(向零取整)
__int128 rem = a % b; // 取模
// ✅ 位运算
__int128 and_op = a & b; // 按位与
__int128 or_op = a | b; // 按位或
__int128 xor_op = a ^ b; // 按位异或
__int128 not_op = ~a; // 按位取反
__int128 left = a << 2; // 左移
__int128 right = a >> 2; // 右移(算术右移)
// ✅ 比较运算
bool eq = (a == b);
bool lt = (a < b);
bool gt = (a > b);
// ... 所有比较运算符都支持
// ✅ 复合赋值
a += b; a -= b; a *= b; a /= b; a %= b;
a &= b; a |= b; a ^= b;
a <<= 2; a >>= 2;
// ✅ 自增自减
a++; ++a; a--; --a;
四、输入输出问题(重点)
标准库完全不支持 __int128 的输入输出,必须手动实现:
输入输出实现
std::ostream& operator<<(std::ostream& os, __int128 n) {
if (n == 0) return os << '0';
std::string s;
bool negative = false;
if (n < 0) {
negative = true;
n = -n;
}
while (n > 0) {
s += '0' + (n % 10);
n /= 10;
}
if (negative) s += '-';
std::reverse(s.begin(), s.end());
return os << s;
}
std::istream& operator>>(std::istream& is, __int128& n) {
std::string s;
is >> s;
n = 0;
bool negative = false;
size_t start = 0;
if (s[0] == '-') {
negative = true;
start = 1;
}
for (size_t i = start; i < s.size(); ++i) {
n = n * 10 + (s[i] - '0');
}
if (negative) n = -n;
return is;
}
在using namespace std;后面加上这行代码,你就能正常cin,cout _int128类型的数了
五、字面量问题
没有直接的128位字面量,需要转换:
// ❌ 错误:直接写大数
__int128 a = 170141183460469231731687303715884105727; // 编译错误
// ✅ 正确方法1:强制转换
__int128 b = (__int128)1234567890123456789LL * 1000000000;
// ✅ 正确方法2:使用宏
#define INT128_C(x) ((__int128)x)
// ✅ 正确方法3:字符串解析
__int128 c = read_int128(); // 从字符串输入
// ✅ 正确方法4:分段构造
__int128 d = ((__int128)987654321 << 64) | 123456789;
六、常见应用场景
1. 大数乘法防溢出
// 计算 a * b % mod(a, b, mod < 2^64)
uint64_t mul_mod(uint64_t a, uint64_t b, uint64_t mod) {
__uint128_t result = (__uint128_t)a * b;
return (uint64_t)(result % mod);
}
// 快速幂取模
uint64_t pow_mod(uint64_t base, uint64_t exp, uint64_t mod) {
__uint128_t result = 1;
while (exp > 0) {
if (exp & 1) result = (result * base) % mod;
base = (__uint128_t)base * base % mod;
exp >>= 1;
}
return (uint64_t)result;
}
2. 精确计算大数
// 计算组合数 C(n, m) 避免溢出
__int128 combination(int n, int m) {
if (m < 0 || m > n) return 0;
if (m > n - m) m = n - m;
__int128 result = 1;
for (int i = 1; i <= m; ++i) {
result = result * (n - m + i) / i;
}
return result;
}
3. 高精度计时/计数器
// 纳秒级计数器
unsigned __int128 get_cycles() {
unsigned __int128 cycles;
// 使用 RDTSC 指令(x86)
uint64_t high, low;
asm volatile("rdtsc" : "=a"(low), "=d"(high));
cycles = ((unsigned __int128)high << 64) | low;
return cycles;
}
4. 密码学应用
// 模拟128位寄存器
__uint128_t rotate_left(__uint128_t value, int shift) {
shift &= 127;
return (value << shift) | (value >> (128 - shift));
}
// AES MixColumns 等操作
注意事项
- 不是标准C++,依赖编译器扩展
- 内存占用:16字节(对齐可能更大)
- 调试困难:调试器可能无法直接显示值
- 序列化问题:不能直接写入文件或网络传输
- 与
long long混用:注意类型提升规则
总结
- ✅ 适合:需要128位精度的性能敏感场景
- ❌ 不适合:需要跨MSVC平台、任意精度、简单IO的场合
- 💡 建议:封装成类来处理IO,或考虑Boost作为替代