pythonbit-manipulationoverflowtwos-complementint32

How to accurately emulate `int32`, signed 2's complement 32-bit integers, in python


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

  1. int32 has INT32_MIN = -(1 << 31) and INT32_MAX = (1 << 31) - 1
  2. Does python use 2's complement?
  3. in 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).
  4. in python, a positive integer is considered to have infinitely (or arbitrarily) many leading ones and a negative integer is considered to have infinitely (or arbitrarily) many leadings ones.

So for example:

123 would look like:

-123 would look like:

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?


Solution

  • 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.