将位串转换为 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)
我正在尝试解决 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)