Python中的二的补码
在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)