I'm using the cpp_int header file from boost/multiprecision and for some reason when I cast -1 to a uint256_t then cast it back to an int256_t, it keeps the same value (~1.15e77). When I increment this variable, it wraps back to 0. What gives. Why is my int256_t acting like a uint256_t?
Apologies for bad formatting, I'm not used to using stack overflow.
I tried printing the int256_t and it printed the same value as the uint26_t, which it shouldn't be able to do. I also tried printing int256_t(-1) and it printed -1 fine. If I compare the int256_t to -1 it equates to false, but if I increment them both and then compare it it equates to true as they're both now 0.
Why is this the case? The max uint256_t should be 0xfff....fff, and a signed 2s complement version of -1 in int256_t is 0xfff....fff as well. Is the boost implementation of integers not 2s complement?
int256_t
uses signed magnitude format for number representation, meaning that it separately stores the information about sign and magnitude of the number:
The type uses a sign-magnitude representation internally, so type int128_t has 128-bits of precision plus an extra sign bit. In this respect the behaviour of these types differs from fundamental (built-in) 2's complement types.
When you cast int256_t
to uint256_t
, you strip information about the sign and get the number that is equal to "0 + the signed number". For negatives, this causes a wrap, so for -1 you get numeric_limits<uint256_t>::max()
. When you cast back, the sign is assumed positive, since by definition unsigned numbers are always positive. The magnitude part of int256_t
is capable of holding the same number of bits as uint256_t
, so the conversion is without loss.
Demonstrating:
#include <iostream>
#include <boost/multiprecision/cpp_int.hpp>
namespace mp = boost::multiprecision;
int main()
{
mp::int256_t si1{-1};
mp::uint256_t ui1{si1};
mp::int256_t si2{ui1};
std::cout << si1 << "\n" << ui1 << "\n" << si2 << std::endl;
}
Prints
-1
115792089237316195423570985008687907853269984665640564039457584007913129639935
115792089237316195423570985008687907853269984665640564039457584007913129639935