使用 32 位整数和操作数
Using 32-bit ints and operands
是否有可能以某种方式覆盖或重载 python 中 ints/numbers 的标准实现,使其像 32 位整数一样工作。
a: int
a = 4076863488
>>> -218103808
或者是否有可能以某种方式定义一个不能改变类型的变量?做类似的事情:x: int
?
我想这样做是因为在每个位操作和赋值上写 ctypes.c_int32(n)
很烦人。特别是因为 Python 不使用 32 位按位操作数。
我知道我基本上是在尝试改变语言的本质。所以也许我问的是如果你必须在 python.
中做 32 位的东西你会怎么做
部分选项:
- 使用 Cython。您可以在那里声明一个本机 32 位 int 类型,您甚至可以获得将纯数字代码编译为(非常)快速的 C 代码的优势。
- 使用单个元素的
numpy
数组:np.zeros((1,), dtype=np.int32)
。如果您只使用就地操作(+=
、*=
等),这将像 32 位 int 类型一样工作。请注意,如果您曾经使用过常规二元运算符(例如 myint + 3
),您可能会进行类型提升或转换,结果将不再是 int32
.
- 使用
ctypes.c_int32
。这内置于 Python,但不支持数学运算,因此您必须自己包装和解包(例如 newval = c_int32(v1.value + v2.value)
)。
- 使用像
fixedint
(无耻插件)这样的库,它提供固定整数 类,通过操作保持固定大小而不是衰减到 int
。 fixedint
是专门为固定宽度的按位数学而设计的。在这种情况下,您将使用 fixedint.Int32
.
一些不太理想的选项:
struct
:如果您的输入超出范围,则会抛出错误。您可以使用 unpack('i', pack('I', val & 0xffffffff))[0]
来解决这个问题,但这真的很笨拙。
array
:如果您尝试存储超出范围的值,则会抛出错误。比 struct
. 更难解决
手动 bitmashing。对于 unsigned 32 位 int,这只是添加很多 & 0xffffffff
的问题,这还算不错。但是,Python 没有任何内置方法将值包装成带符号的 32 位整数,因此您必须编写自己的 int32
转换函数并将所有操作包装成它:
def to_int32(val):
val &= ((1<<32)-1)
if val & (1<<31): val -= (1<<32)
return val
您的选项演示:
赛通
cpdef int munge(int val):
cdef int x
x = val * 32
x += 0x7fffffff
return x
另存为int_test.pyx
并用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)
固定整数
import fixedint
def munge(val):
x = val * 32
x += 0x7fffffff
return x
print(munge(fixedint.Int32(3)))
# prints -2147483553
是否有可能以某种方式覆盖或重载 python 中 ints/numbers 的标准实现,使其像 32 位整数一样工作。
a: int
a = 4076863488
>>> -218103808
或者是否有可能以某种方式定义一个不能改变类型的变量?做类似的事情:x: int
?
我想这样做是因为在每个位操作和赋值上写 ctypes.c_int32(n)
很烦人。特别是因为 Python 不使用 32 位按位操作数。
我知道我基本上是在尝试改变语言的本质。所以也许我问的是如果你必须在 python.
中做 32 位的东西你会怎么做部分选项:
- 使用 Cython。您可以在那里声明一个本机 32 位 int 类型,您甚至可以获得将纯数字代码编译为(非常)快速的 C 代码的优势。
- 使用单个元素的
numpy
数组:np.zeros((1,), dtype=np.int32)
。如果您只使用就地操作(+=
、*=
等),这将像 32 位 int 类型一样工作。请注意,如果您曾经使用过常规二元运算符(例如myint + 3
),您可能会进行类型提升或转换,结果将不再是int32
. - 使用
ctypes.c_int32
。这内置于 Python,但不支持数学运算,因此您必须自己包装和解包(例如newval = c_int32(v1.value + v2.value)
)。 - 使用像
fixedint
(无耻插件)这样的库,它提供固定整数 类,通过操作保持固定大小而不是衰减到int
。fixedint
是专门为固定宽度的按位数学而设计的。在这种情况下,您将使用fixedint.Int32
.
一些不太理想的选项:
struct
:如果您的输入超出范围,则会抛出错误。您可以使用unpack('i', pack('I', val & 0xffffffff))[0]
来解决这个问题,但这真的很笨拙。array
:如果您尝试存储超出范围的值,则会抛出错误。比struct
. 更难解决
手动 bitmashing。对于 unsigned 32 位 int,这只是添加很多
& 0xffffffff
的问题,这还算不错。但是,Python 没有任何内置方法将值包装成带符号的 32 位整数,因此您必须编写自己的int32
转换函数并将所有操作包装成它:def to_int32(val): val &= ((1<<32)-1) if val & (1<<31): val -= (1<<32) return val
您的选项演示:
赛通
cpdef int munge(int val):
cdef int x
x = val * 32
x += 0x7fffffff
return x
另存为int_test.pyx
并用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)
固定整数
import fixedint
def munge(val):
x = val * 32
x += 0x7fffffff
return x
print(munge(fixedint.Int32(3)))
# prints -2147483553