Jim*_*Jim 58 python bit-manipulation twos-complement
python中是否有内置函数将二进制字符串(例如'111111111111')转换为二进制补码整数 -1?
tra*_*avc 65
(1<<bits)如果最高位为1 ,则二进制补码减去.例如,以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
Run Code Online (Sandbox Code Playgroud)
从二进制字符串开始特别容易......
binary_string = '1111' # or whatever... no '0b' prefix
out = twos_comp(int(binary_string,2), len(binary_string))
Run Code Online (Sandbox Code Playgroud)
对我来说更有用的是从十六进制值(本例中为32位)...
hex_string = '0xFFFFFFFF' # or whatever... '0x' prefix doesn't matter
out = twos_comp(int(hex_string,16), 32)
Run Code Online (Sandbox Code Playgroud)
Sco*_*ths 20
它不是内置的,但如果你想要不寻常的长度数,那么你可以使用bitstring模块.
>>> from bitstring import Bits
>>> a = Bits(bin='111111111111')
>>> a.int
-1
Run Code Online (Sandbox Code Playgroud)
可以通过多种方式等效地创建相同的对象,包括
>>> b = Bits(int=-1, length=12)
Run Code Online (Sandbox Code Playgroud)
它只是一个任意长度的字符串,并使用属性来获得不同的解释:
>>> print a.int, a.uint, a.bin, a.hex, a.oct
-1 4095 111111111111 fff 7777
Run Code Online (Sandbox Code Playgroud)
Gaë*_*ard 10
从Python 3.2开始,有用于字节操作的内置函数:https://docs.python.org/3.4/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)
Run Code Online (Sandbox Code Playgroud)
校验:
twos('11111111', 1) # gives -1
twos('01111111', 1) # gives 127
Run Code Online (Sandbox Code Playgroud)
对于旧版本的Python,travc的答案很好但如果想要使用整数而不是字符串,它对负值不起作用.对于每个val,f(f(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
Run Code Online (Sandbox Code Playgroud)
>>> bits_in_word=12
>>> int('111111111111',2)-(1<<bits_in_word)
-1
Run Code Online (Sandbox Code Playgroud)
这是因为:
二进制数的二进制补码定义为通过从2的大次幂中减去该数得到的值(具体地,对于N位二进制补码,从2 ^ N减去).数字的二进制补码在大多数算术中表现得像原始数的负数,并且它可以以自然的方式与正数共存.
这将使用按位逻辑有效地为您提供二进制补码:
def twos_complement(value, bitWidth):
if value >= 2**bitWidth:
# This catches when someone tries to give a value that is out of range
raise ValueError("Value: {} out of range of {}-bit value.".format(value, bitWidth))
else:
return value - int((value << 1) & 2**bitWidth)
Run Code Online (Sandbox Code Playgroud)
这个怎么运作:
首先,我们确保用户向我们传递了一个在所提供位范围内的值(例如,有人给了我们 0xFFFF 并指定了 8 位)该问题的另一种解决方案是按位 AND (&) 将值与(2**位宽)-1
为了得到结果,该值向左移动 1 位。这将值(符号位)的 MSB 移动到要与 和的位置2**bitWidth。当符号位为“0”时,减数变为 0,结果为value - 0。当符号位为“1”时,减数变为2**bitWidth,结果为value - 2**bitWidth
示例 1:如果参数为 value=0xFF (255d, b11111111) 和 bitWidth=8
示例 2:如果参数为 value=0x1F (31d, b11111) 和 bitWidth=6
示例 3:值 = 0x80,位宽 = 7
ValueError: Value: 128 out of range of 7-bit value.
示例 4:值 = 0x80,bitWitdh = 8
现在,使用其他人已经发布的内容,将您的位串传递到 int(bitstring,2) 并传递给 twos_complement 方法的 value 参数。
几个实现(仅作为说明,不用于使用):
def to_int(bin):
x = int(bin, 2)
if bin[0] == '1': # "sign bit", big-endian
x -= 2**len(bin)
return x
def to_int(bin): # from definition
n = 0
for i, b in enumerate(reversed(bin)):
if b == '1':
if i != (len(bin)-1):
n += 2**i
else: # MSB
n -= 2**i
return n
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
97434 次 |
| 最近记录: |