Some options:
- Use Cython. You can declare a native 32-bit int type there, and you even get the advantage that pure numerical code gets compiled to (very) fast C code.
- Use a
numpy
array of a single element: np.zeros((1,), dtype=np.int32)
. Provided you only ever use in-place operations (+=
, *=
, etc.), this will work like a 32-bit int type. Do be aware that if you ever use a regular binary operator (e.g. myint + 3
), you might be subjected to type promotion or conversion, and the result will no longer be int32
.
- Use
ctypes.c_int32
. This comes built-in to Python, but supports no mathematical operations so you have to wrap and unwrap yourself (e.g. newval = c_int32(v1.value + v2.value)
).
- Use a library like
fixedint
(shameless plug), which provides fixed-integer classes that remain fixed size through operations rather than decaying to int
. fixedint
was specifically designed with fixed-width bitwise math in mind. In this case you would use fixedint.Int32
.
Some less desirable options:
struct
: Throws errors if your input is out of range. You can work around this with unpack('i', pack('I', val & 0xffffffff))[0]
, but that's really unwieldy.
array
: Throws errors if you try to store a value out of range. Harder to work around than struct
.
Manual bitmashing. With an unsigned 32-bit int, this is just a matter of adding & 0xffffffff
a lot, which is not too bad. But, Python doesn't have any built-in way to wrap a value to a signed 32-bit int, so you'll have to write your own int32
conversion function and wrap all your operations with it:
def to_int32(val):
val &= ((1<<32)-1)
if val & (1<<31): val -= (1<<32)
return val
Demonstrations of your options:
Cython
cpdef int munge(int val):
cdef int x
x = val * 32
x += 0x7fffffff
return x
Save as int_test.pyx
and compile with cythonize -a -i int_test.pyx
.
>>> import int_test
>>> int_test.munge(3)
-2147483553
NumPy
import numpy as np
def munge(val):
x = val.copy()
x *= 32
x += 0x7fffffff
return x
def to_int32(val):
return np.array((val,), dtype=np.int32)
print(munge(to_int32(3)))
# prints [-2147483553]
ctypes
from ctypes import c_int32
def munge(val):
x = c_int32(val.value * 32)
x = c_int32(x.value + 0x7fffffff)
return x
print(munge(c_int32(3)))
# prints c_int(-2147483553)
fixedint
import fixedint
def munge(val):
x = val * 32
x += 0x7fffffff
return x
print(munge(fixedint.Int32(3)))
# prints -2147483553