将位串转换为 32 位有符号整数会产生错误的结果

Converting bitstring to 32-bit signed integer yields wrong result

我正在尝试解决 this 网站上的挑战。除了无法将位串正确转换为其 32 位带符号整数表示之外,我一切都正确。

例如我有这个位串:

block = '10101010001000101110101000101110'

我自己将此位串转换为 32 位有符号整数的方法:我部分记得在学校时第一位是符号位。如果它是 1,我们有负数,反之亦然。

当我这样做时,它给我以 10 为基数的数字。它只是将它转换为以 10 为基数:

int(block, 2) #yields 2854414894

我尝试排除第一位并转换剩余的31长度位串,然后检查第一位以确定这是不是负数:

int(block[1:32], 2) #yields 706931246

但正确答案是-1440552402。我应该对该位串执行什么操作才能获得该整数?系统的字节顺序是小端还是大端是否相关?我的系统是小端。

在 python 中没有整数的大小,所以你永远不会得到高位 1 位的负值。

对于 "emulate" 32 位行为只需执行此操作,因为您的 2854414894 值 > 2**31-1 又名 0x7FFFFFFF:

print(int(block[1:32], 2)-2**31)

你会得到

-1440552402

您应该检查输入值何时超出 32 位有符号整数的正范围:

res = int(block, 2)
if res >= 2**31:
    res -= 2**32

所以首先你将数字解释为 unsigned 数字,但是当你注意到符号位已设置( >= 2^31 )时,你减去 2^32 所以得到负数。

你说得对,高位决定符号,但这不是一个简单的标志。相反,负数的整个字符被反转。这是一个正数 1(8 位):

00000001

这是负数1:

11111111

结果就是加减"wrap around"。所以 4 - 1 将是:

0100 - 0001 = 0011

因此 0 - 1 与 1_0000_0000 - 1 相同。"borrow" 刚好超出整数的顶部。

"negate" 数字的一般方法是 "invert the bits, add 1"。这是双向的,所以你可以从积极到消极再回来。

在你的情况下,使用前导'1'来检测是否需要取反,然后转换为int,然后可能执行取反步骤。但是请注意,因为 python 的 int 不是 一个 fixed-width 值,所以有一个单独的内部标志(Python int 不是一个“32 位”数字,它是一个 arbitrary-precision 整数,动态分配的表示以某种方式存储,而不是简单的 2 的补码)。

block = '10101010001000101110101000101110'
asnum = int(block, 2)
if block[0] == '1':
    asnum ^= 0xFFFFFFFF
    asnum += 1
    asnum = -asnum

print(asnum)