【问题标题】:Converting bitstring to 32-bit signed integer yields wrong result将位串转换为 32 位有符号整数会产生错误的结果
【发布时间】:2017-02-12 05:20:00
【问题描述】:

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

例如我有这个位串:

block = '10101010001000101110101000101110'

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

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

int(block, 2) #yields 2854414894

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

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

但正确答案是-1440552402。我应该对这个位串做什么操作才能得到这个整数?如果系统的字节顺序是小端还是大端,是否相关?我的系统是小端的。

【问题讨论】:

标签: python python-2.7 bits


【解决方案1】:

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

要“模拟” 32 位行为,只需执行此操作,因为您的 2854414894 值是 > 2**31-1 aka 0x7FFFFFFF

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

你会得到

-1440552402

【讨论】:

    【解决方案2】:

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

    00000001
    

    这是一个负数 1:

    11111111
    

    结果是加法和减法“环绕”。所以 4 - 1 将是:

    0100 - 0001 = 0011
    

    因此 0 - 1 与 1_0000_0000 - 1 相同。“借位”刚好超出整数的顶部。

    “否定”数字的一般方法是“反转位,加 1”。这是双向的,因此您可以从正面到负面再返回。

    在您的情况下,使用前导 '1' 来检测是否需要否定,然后转换为 int,然后可能执行否定步骤。但是请注意,由于 python 的 int 不是 固定宽度值,因此有一个单独的内部标志(Python int 不是“32 位”数字,它是任意的——精度整数,动态分配的表示以某种方式存储,而不是简单的 2 的补码)。

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

    【讨论】:

    • 它解决了我的问题。谢谢。然而,为什么我们异或asnum?你也能解释一下吗?
    • 用 FFFF(全 1 位)对数字进行异或运算会反转位。 1变成0,0变成1。
    • 哦,我明白了。它是一个人的补充。我们不能只使用~ 运算符吗?
    • 你当然可以。随意!
    【解决方案3】:

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

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

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

    【讨论】:

      猜你喜欢
      • 2013-12-22
      • 1970-01-01
      • 2019-05-30
      • 2014-09-22
      • 1970-01-01
      • 1970-01-01
      • 2019-08-15
      • 2021-10-06
      • 1970-01-01
      相关资源
      最近更新 更多