如何在 python 中准确模拟 `int32`,有符号 2 的补码 32 位整数
How to accurately emulate `int32`, signed 2's complement 32-bit integers, in python
Python 支持任意位长度的整数,但我想模仿 int32
,32 位整数,在它们所有的溢出荣耀中。
我对此没有什么问题和意见
int32
有 INT32_MIN = -(1 << 31)
和 INT32_MAX = (1 << 31) - 1
- python是否使用 2 的补码?
- 在
int32
中,正数 int32
的前导零一直到第 31 位,负数 int32
的前导 1 一直到第 31 位(这是因为它们是 2补充)。
- 在python中,正整数被认为有无限(或任意)多个前导数,负整数被认为有无限(或任意)多个前导数。
例如:
123
看起来像:
0b0000_0000_0000_0000_0000_0000_0111_1011
在 int32
0b...0_0111_1011
in python(...0
表示无限多前导0
)
-123
看起来像:
0b1111_1111_1111_1111_1111_1111_1000_0101
在 int32
0b...1_1000_0101
in python(...1
表示无限多前导1
)
考虑到这一切,我想出了这个代码来模拟 int32
,但想要检查一下:
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
当您将 1
添加到 INT32_MAX
或从 INT32_MIN
中减去 1
时,它似乎确实会溢出,所以这让我有信心它是正确的,但这只是两个测试用例。这对你来说正确吗?
看起来是正确的,你对二进制补码的理解和 Python 对它们的理解也是正确的。实现可以简化,对于简化的一些定义(可能比较难掌握)。
或者也可以这样做:
def int32(x):
x = x & 0xffffffff
return (x ^ 0x80000000) - 0x80000000
第一行很明显,第二行通过用 XOR 翻转符号然后用减法翻转它来执行符号扩展,如果需要,这也会设置无限前导位。
- 如果符号为零,则 XOR 设置它,减法重置它,没有任何有趣的事情发生。
- 如果符号是 1,则 XOR 将其重置,减法将其设置但也会产生借位,因此将设置下一位,依此类推。值得庆幸的是,这不需要无限的时间,无限的前导位是隐式的,实际上并不是一一计算的。
Python 支持任意位长度的整数,但我想模仿 int32
,32 位整数,在它们所有的溢出荣耀中。
我对此没有什么问题和意见
int32
有INT32_MIN = -(1 << 31)
和INT32_MAX = (1 << 31) - 1
- python是否使用 2 的补码?
- 在
int32
中,正数int32
的前导零一直到第 31 位,负数int32
的前导 1 一直到第 31 位(这是因为它们是 2补充)。 - 在python中,正整数被认为有无限(或任意)多个前导数,负整数被认为有无限(或任意)多个前导数。
例如:
123
看起来像:
0b0000_0000_0000_0000_0000_0000_0111_1011
在int32
0b...0_0111_1011
in python(...0
表示无限多前导0
)
-123
看起来像:
0b1111_1111_1111_1111_1111_1111_1000_0101
在int32
0b...1_1000_0101
in python(...1
表示无限多前导1
)
考虑到这一切,我想出了这个代码来模拟 int32
,但想要检查一下:
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
当您将 1
添加到 INT32_MAX
或从 INT32_MIN
中减去 1
时,它似乎确实会溢出,所以这让我有信心它是正确的,但这只是两个测试用例。这对你来说正确吗?
看起来是正确的,你对二进制补码的理解和 Python 对它们的理解也是正确的。实现可以简化,对于简化的一些定义(可能比较难掌握)。
或者也可以这样做:
def int32(x):
x = x & 0xffffffff
return (x ^ 0x80000000) - 0x80000000
第一行很明显,第二行通过用 XOR 翻转符号然后用减法翻转它来执行符号扩展,如果需要,这也会设置无限前导位。
- 如果符号为零,则 XOR 设置它,减法重置它,没有任何有趣的事情发生。
- 如果符号是 1,则 XOR 将其重置,减法将其设置但也会产生借位,因此将设置下一位,依此类推。值得庆幸的是,这不需要无限的时间,无限的前导位是隐式的,实际上并不是一一计算的。