Python中的二的补码

96 投票
20 回答
210137 浏览
提问于 2025-04-15 15:16

在Python中,有没有什么内置的函数可以把一个二进制字符串,比如说'111111111111',转换成二进制补码表示的-1呢?

20 个回答

23

这个功能并不是内置的,但如果你想要一些不寻常长度的数字,可以使用bitstring模块。

>>> from bitstring import Bits
>>> a = Bits(bin='111111111111')
>>> a.int
-1

同一个对象可以通过几种不同的方式来创建,包括:

>>> b = Bits(int=-1, length=12)

它就像是一串任意长度的二进制位,并且可以通过不同的属性来获得不同的解释:

>>> print a.int, a.uint, a.bin, a.hex, a.oct
-1 4095 111111111111 fff 7777
33

从Python 3.2开始,Python里有一些内置的函数可以用来处理字节数据,你可以在这里找到相关信息:https://docs.python.org/3/library/stdtypes.html#int.to_bytes

通过结合使用to_bytes和from_bytes这两个函数,你可以得到:

def twos(val_str, bytes):
    import sys
    val = int(val_str, 2)
    b = val.to_bytes(bytes, byteorder=sys.byteorder, signed=False)                                                          
    return int.from_bytes(b, byteorder=sys.byteorder, signed=True)

检查一下:

twos('11111111', 1)  # gives -1
twos('01111111', 1)  # gives 127

对于旧版本的Python,travc的回答是不错的,但如果你想处理整数而不是字符串,它在处理负数时就不太管用了。这里有一个二进制补码的函数,满足f(f(val)) == val对于每个val都成立:

def twos_complement(val, nbits):
    """Compute the 2's complement of int value val"""
    if val < 0:
        val = (1 << nbits) + val
    else:
        if (val & (1 << (nbits - 1))) != 0:
            # If sign bit is set.
            # compute negative value.
            val = val - (1 << nbits)
    return val
101

二进制补码在最高位是1的时候,会减去 (1<<bits)。以8位为例,这样的范围是从127到-128。

这是一个计算整数补码的函数...

def twos_comp(val, bits):
    """compute the 2's complement of int value val"""
    if (val & (1 << (bits - 1))) != 0: # if sign bit is set e.g., 8bit: 128-255
        val = val - (1 << bits)        # compute negative value
    return val                         # return positive value as is

从二进制字符串转换特别简单...

binary_string = '1111' # or whatever... no '0b' prefix
out = twos_comp(int(binary_string,2), len(binary_string))

对我来说,从十六进制值转换更有用(这个例子是32位)...

hex_string = '0xFFFFFFFF' # or whatever... '0x' prefix doesn't matter
out = twos_comp(int(hex_string,16), 32)

撰写回答