首页 > 解决方案 > 如何在python中准确模拟`int32`,有符号2的补码32位整数

问题描述

Python 支持任意位长度的整数,但我想模拟int3232 位整数的所有溢出荣耀。

我对此有几个问题和意见

  1. int32INT32_MIN = -(1 << 31)并且INT32_MAX = (1 << 31) - 1
  2. python是否使用2的补码?
  3. 在 中int32,正int32数的前导零一直到第 31 位,负数的前导零一直到第int3231 位(这是因为它们是 2 的补码)。
  4. 在python中,正整数被认为具有无限(或任意)多个前导数,负整数被认为具有无限(或任意)多个前导数。

例如:

123看起来像:

-123看起来像:

鉴于这一切,我想出了这段代码来 emulate 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或减去1时,它似乎确实会溢出INT32_MIN,所以这让我相信它是正确的,但这只是两个测试用例。这对您来说是否正确?

标签: pythonbit-manipulationoverflowtwos-complementint32

解决方案


它看起来是正确的,并且您对二进制补码整数和 Python 对它们的理解也是正确的。对于简化的某些定义(可能更难掌握),可以简化实现。

或者,它可以这样做:

def int32(x):
    x = x & 0xffffffff
    return (x ^ 0x80000000) - 0x80000000

第一行很明显,第二行通过用 XOR 翻转符号然后用减法将其翻转回来来执行符号扩展,如果需要,这也将设置无限的前导位。

  • 如果符号为零,则 XOR 设置它,减法重置它,没有任何有趣的事情发生。
  • 如果符号为 1,则 XOR 将其重置,减法将其设置但也会产生借位,因此将设置下一位,依此类推。值得庆幸的是,这并不需要无限的时间,无限的前导位是隐含的,实际上并未逐一计算。

推荐阅读