Python supports arbitrary bit-length integers, but I would like to emulate int32
, 32-bit integers, in all their overflow glory.
I have few questions and comments about this
int32
has INT32_MIN = -(1 << 31)
and INT32_MAX = (1 << 31) - 1
int32
, a positive int32
has leading zeros up to the 31st bit and a negative int32
has leading ones up to the 31st bit (this is because they are 2's complement).So for example:
123
would look like:
0b0000_0000_0000_0000_0000_0000_0111_1011
in int32
0b...0_0111_1011
in python (...0
indicates infinitely many leading 0
's)-123
would look like:
0b1111_1111_1111_1111_1111_1111_1000_0101
in int32
0b...1_1000_0101
in python (...1
indicates infinitely many leading 1
's)Given all this, I've come up with this code to emulate int32
, but would like a check:
INT32_MIN = -(1 << 31)
INT32_MAX = (1 << 31) - 1
INT32_MASK = (1 << 32) - 1
INT32_SIGNBIT = 1 << 31
def int32(x):
sb = bool(x & INT32_SIGNBIT)
i32 = x & INT32_MASK
if sb:
i32 += ~INT32_MASK
return i32
a = int32(INT32_MAX + 1)
b = int32(INT32_MIN - 1)
aa = a == INT32_MIN
bb = b == INT32_MAX
It does seem to overflow as desired when you add 1
to INT32_MAX
or subtract 1
from INT32_MIN
, so that gives me some confidence that it is correct, but that's just two test cases. Does this look correct to you?
It looks correct, and your understanding of two's complement integers and Pythons take on them is also correct. The implementation can be simplified, for some definition of simplification (maybe it's more difficult to grasp).
Alternatively it could be done like this:
def int32(x):
x = x & 0xffffffff
return (x ^ 0x80000000) - 0x80000000
The first line is obvious, the second line performs sign-extension by flipping the sign with an XOR and then flipping it back with a subtraction which will also set the infinite leading bits if necessary.