Ekrem Dinçel
Ekrem Dinçel

Reputation: 1141

Python distribute 8 bits into beginnings of 4 x 8 bits, two by two

I have an integer that is 8 bits and I want to distribute these bits into beginnings of 4 integers (4x8 bit) two by two. For example:

bit_8 = 0b_10_11_00_11
bit_32 = b"\x12\x32\x23\54" # --> [0b100_10, 0b1100_10, 0b1000_11, 0b1011_00]

what_i_want = [0b100_10, 0b1100_11, 0b1000_00, 0b1011_11]

For readability I wrote numbers in a list, but I want them as bytes. I am not very good at bit manipulations and I couldn't find a good way. I will repeat this process many times, so I need a fast solution. I found a way of setting bits by one by at here, but I wonder if there is a better way for my problem.

Language is not so important, I need an algorithm. Nevertheless I prefer Python.

Upvotes: 0

Views: 150

Answers (1)

Thierry Lathuille
Thierry Lathuille

Reputation: 24262

You could do it by iterating in reverse on bit_32, and at the same time taking the last two bits of bit_8, then shifting it right. This way, you can build a list of the output values, in reverse order, which you can reorder while converting to bytes.

bit_8 = 0b_10_11_00_11
bit_32 = b"\x12\x32\x23\54" # --> [0b100_10, 0b1100_10, 0b1000_11, 0b1011_00]

what_i_want = [0b100_10, 0b1100_11, 0b1000_00, 0b1011_11]

out_lst = []
for b in reversed(bit_32):
    bits_from_bit_8 = bit_8 & 0b11  # last two bits of bit_8
    bit_8 >>= 2  # we shift it right by to bits 
    out_lst.append(b & 0b11111100 | bits_from_bit_8) 
out = bytes(reversed(out_lst))

print(out)
#b'\x123 /'

# Check that this is the expected output:
print([i for i in out], what_i_want)
# [18, 51, 32, 47] [18, 51, 32, 47]

Upvotes: 1

Related Questions