Python: извлечение битов из байта
Я читаю двоичный файл в python, и в документации для формата файла говорится:
Флаг (в двоичном выражении) Значение
1 nnn nnnn Указывает, что имеется один байт данных который должен быть дублирован nnn nnnn (максимум 127) раз.
0 nnn nnnn Указывает, что есть nnn nnnn байты изображения данные для наблюдения (максимум 127 байт) и нет дубликатов.
n 000 0000 Поле конца строки. Обозначает конец строки запись. Значение n может быть либо нулевым, либо одним. Обратите внимание, что поле конца строки требуется и что он отражается в длине записи строки поле, упомянутое выше.
При чтении файла я ожидаю, что байт я должен вернуть 1 nnn nnnn
, где часть nnn nnnn
должна быть 50.
Я смог сделать это, используя следующее:
flag = byte >> 7
numbytes = int(bin(byte)[3:], 2)
Но вычисление numbytes похоже на дешевое обходное решение.
Могу ли я сделать больше бит математики, чтобы выполнить вычисление numbytes?
Как вы подходите к этому?
Ответы
Ответ 1
Вы можете отключить ведущий бит, используя маску ANDed с байтом из файла. Это оставит вас со значением остальных бит:
mask = 0b01111111
byte_from_file = 0b10101010
value = mask & byte_from_file
print bin(value)
>> 0b101010
print value
>> 42
Я считаю, что двоичные числа легче понять, чем hex при выполнении маскировки.
EDIT: чуть более полный пример для вашего варианта использования:
LEADING_BIT_MASK = 0b10000000
VALUE_MASK = 0b01111111
bytes = [0b10101010, 0b01010101, 0b0000000, 0b10000000]
for byte in bytes:
value = byte & VALUE_MASK
has_leading_bit = byte & LEADING_BIT_MASK
if value == 0:
print "EOL"
elif has_leading_bit:
print "leading one", value
elif not has_leading_bit:
print "leading zero", value
Ответ 2
Классический подход проверки того, установлен ли бит, заключается в использовании двоичного "и" оператора, т.е.
x = 10 # 1010 in binary
if x & 0b10 != 0:
print('Second bit is set')
Чтобы проверить, установлен ли n ^ -й бит, используйте значение 2, т.е.
def is_set(x, n):
return x & 2**n != 0
is_set(10, 1) # 1 because we count from 0th bit
>>> True
Ответ 3
Если я правильно прочитал ваше описание:
if (byte & 0x80) != 0:
num_bytes = byte & 0x7F
Ответ 4
Всегда смотрите стандартную документацию и Google для сторонних пакетов: http://pypi.python.org/pypi/BitVector/3.0
Ответ 5
Не уверен, что я правильно вас понял, но если бы я это сделал, это должно было сделать трюк:
>>> x = 154 #just an example
>>> flag = x >> 1
>>> flag
1
>>> nb = x & 127
>>> nb
26
Ответ 6
Вы можете сделать это следующим образом:
def GetVal(b):
# mask off the most significant bit, see if it set
flag = b & 0x80 == 0x80
# then look at the lower 7 bits in the byte.
count = b & 0x7f
# return a tuple indicating the state of the high bit, and the
# remaining integer value without the high bit.
return (flag, count)
>>> testVal = 50 + 0x80
>>> GetVal(testVal)
(True, 50)
Ответ 7
там вы идете:
class ControlWord(object):
"""Helper class to deal with control words.
Bit setting and checking methods are implemented.
"""
def __init__(self, value = 0):
self.value = int(value)
def set_bit(self, bit):
self.value |= bit
def check_bit(self, bit):
return self.value & bit != 0
def clear_bit(self, bit):
self.value &= ~bit
Ответ 8
Вместо int (bin (byte) [3:], 2) вы можете просто использовать: int (bin (byte → 1), 2)