Working with 128-bit Integers in C++
What this code does (short)
The code defines a 128-bit integer type for GNU C++ (__int128) and provides two stream operators so you can use cin >> and cout << with that type. This is useful because the standard iostream library does not know how to read or print __int128.
Line-by-line explanation
// for: GNU C++20 (64)
using i128 = __int128;
const i128 ONE_128 = i128(1);
const i128 ZERO_128 = i128(0);
-
using i128 = __int128;creates an aliasi128for the builtin GNU type__int128. -
__int128is a 128-bit signed integer available in GNU compilers on 64-bit systems. It stores much bigger values thanlong long. -
These two lines define constants
ONE_128andZERO_128with values1and0typed asi128. -
They make the code clearer when you need literal 128-bit constants.
Input operator: operator >>
std::istream &operator>>(std::istream &is, i128 &n) {
n = 0;
std::string s; is >> s;
for (auto c : s) {
n = 10 * n + c - '0';
}
return is;
}
-
This overload lets you write
cin >> my_i128_variable;. -
Steps it performs:
- Set
nto zero. - Read the whole token from the stream into a
std::string s. This skips leading whitespace and reads until the next whitespace. - For each character
cin the string, it updatesn = 10*n + (c - '0'). That converts the decimal digits to a numeric value. - Return the input stream reference so chaining (e.g.,
cin >> a >> b;) works.
- Set
-
Important limitations:
- The code assumes the string contains only digits (
'0'–'9'). It does not handle a leading-sign, a leading+, or invalid characters. - It does not check for overflow. If the number in the input is larger than 128 bits can hold, the behavior is undefined (it will wrap or give wrong results).
- The code assumes the string contains only digits (
Output operator: operator <<
std::ostream &operator<<(std::ostream &os, i128 n) {
if (n == 0) {
return os << 0;
}
std::string s;
while (n > 0) {
s += '0' + n % 10;
n /= 10;
}
std::reverse(s.begin(), s.end());
return os << s;
}
-
This overload lets you write
cout << my_i128_variable;. -
Steps it performs:
- If
nis zero, it prints0and returns. - Otherwise it builds a string
swith the digits ofnin reverse order: taken % 10to get the last digit, append the corresponding character, and then dividenby 10. - Reverse the string to get the correct digit order.
- Output the string and return the stream.
- If
⚠️ Warning:
The provided code only works correctly for positive integers. It does not support negative numbers or the sign -, and printing a negative i128 will also produce incorrect output.
-
Important limitations:
- The code assumes
nis non-negative. Ifnis negative, thewhile (n > 0)loop never runs and the result is wrong. Typical fix: checkif (n < 0) { os << '-'; n = -n; }before converting digits. - Converting a 128-bit integer to decimal takes time proportional to the number of digits (about 39 digits max for 128-bit), which is fine for competitive programming.
- The code assumes
How to use
i128 a;
cin >> a;
cout << a << '\n';