Search code examples
pythonbit-manipulationbitwise-operators

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.


Solution

  • 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]