Упаковка 4 Целые числа как ONE BYTE?
У меня есть четыре целых числа { a
, b
, c
, d
}, которые могут иметь следующий диапазон значений:
a
- {0 или 1} (1 бит)
b
- {0 или 1} (1 бит)
c
- {0, 1, 2,..., 7} (3 бита)
d
- {0, 1, 2,..., 7} (3 бита)
Сначала я хотел бы упаковать их в один байт, который затем можно записать в двоичный файл. позже я хотел бы распаковать этот один байт и получить от него кортеж в форме (a
, b
, c
, d
).
Я знаю, как читать/записывать байт в двоичный файл в Python. Но как мне сделать упаковку/распаковку битов?
Ответы
Ответ 1
Используйте shift и побитовое ИЛИ, затем преобразуйтесь в символ, чтобы получить "байт":
x = chr(a | (b << 1) | (c << 2) | (d << 5))
Чтобы снова распаковать этот байт, сначала преобразуйте его в целое число, затем сдвиньте и используйте побитовое значение AND:
i = ord(x)
a = i & 1
b = (i >> 1) & 1
c = (i >> 2) & 7
d = (i >> 5) & 7
Объяснение: Первоначально у вас есть
0000000a
0000000b
00000ccc
00000ddd
Левые смены дают вам
0000000a
000000b0
000ccc00
ddd00000
Побитовое ИЛИ приводит к
dddcccba
Преобразование в символ преобразует его в один байт.
Распаковка: четыре разных сдвига вправо приводят к
dddcccba
0dddcccb
00dddccc
00000ddd
Маскирование (побитовое И) с помощью 1
(0b00000001
) или 7
(0b00000111
) приводит к
0000000a
0000000b
00000ccc
00000ddd
снова.
Ответ 2
def encode(a, b, c, d):
return a | b << 1 | c << 2 | d << 5
def decode(x):
return x & 1, (x >> 1) & 1, (x >> 2) & 7, (x >> 5) & 7
Ответ 3
Если вам понадобится такая вещь, то переключение бит может стать утомительным и подверженным ошибкам. Есть сторонние библиотеки, которые могут помочь - я написал один из них: bitstring:
Чтобы упаковать и преобразовать в байт:
x = bitstring.pack('2*uint:1, 2*uint:3', a, b, c, d).bytes
и распаковать:
a, b, c, d = bitstring.BitArray(bytes=x).unpack('2*uint:1, 2*uint:3')
Это, вероятно, слишком велико для вашего примера, но полезно, когда ситуация усложняется.
Ответ 4
Довольно просто. Маска (для диапазона), сдвиньте их на место и/или вместе.
packed = ((a & 1) << 7) | ((b & 1) << 6) | ((c & 7) << 3) | (d & 7)
a = (packed >> 7) & 1
b = (packed >> 6) & 1
c = (packed >> 3) & 7
d = packed & 7