Операции в python с отдельными битами байт кода

Необходимо в списке [b'\x9c', b'\x09', b'\xfe', b'\x63'], у каждого элемента списка отнять последние 2 бита, которые определены заранее. 00, 01, 10, 11 соответственно (порядок байтов в списке может быть любой). Затем полученные шестибитые результаты склеить, получив одно двоичное число состоящее из 24х битов. Последовательность этих шестибитных чисел в результате, определяется двумя выкинутыми битами из конца каждого байта. 00 - первое, 01 - второе, 10 - третье, 11 - четвёртое.

data = [b'\x9c', b'\x09', b'\xfe', b'\x63']

for input_data in data:
    print(input_data)

    if str(bin(input_data[0]))[-2:] == "00":
        a1 = int(int.from_bytes(input_data, byteorder="big") / 4)
    elif str(bin(input_data[0]))[-2:] == "01":
        a2 = int((int.from_bytes(input_data, byteorder="big") - 0b01) / 4)
    elif str(bin(input_data[0]))[-2:] == "10":
        a3 = int((int.from_bytes(input_data, byteorder="big") - 0b10) / 4)
    elif str(bin(input_data[0]))[-2:] == "11":
        a4 = int((int.from_bytes(input_data, byteorder="big") - 0b11) / 4)

a1 = int.to_bytes(a1, byteorder="big", length=1)
a2 = int.to_bytes(a2, byteorder="big", length=1)
a3 = int.to_bytes(a3, byteorder="big", length=1)
a4 = int.to_bytes(a4, byteorder="big", length=1)

result = a1 + a2 + a3 + a4
print(bin(int.from_bytes(result, byteorder="big")))

После выполнения данного кода я получаю результат 0b100111000000100011111100011000. В этом результате 30 бит. Происходит это из-за того что при переводе из int в bytes в начале этого числа, если оно короче 8 бит, дописываются нули, и после сложения байтов в строке result = a1 + a2 + a3 + a4 получаются лишние нули в середине двоичного числа. И как следствие не тот результат, который требуется.


Ответы (1 шт):

Автор решения: CrazyElf

Ну вот так будет гораздо короче и более универсально (нет жёсткой привязки к количеству байт в списке):

lst = [b'\x9c', b'\x09', b'\xfe', b'\x63']
arr = []
for b in lst:
    b = int.from_bytes(b, byteorder="big")
    arr.append((b & 0b11, b >> 2))
s = ''.join(f'{x:06b}' for _,x in sorted(arr))
print(s, len(s))

Вывод:

100111000010111111011000 24

Я здесь пользуюсь сортировкой кортежей. В первом элементе кортежа получается номер байта, во втором значение.

→ Ссылка