1

I have 4 variable between 0~0x1FF(9-bit) and 1 variable between 0~0xF(4-bit) and I want to pack them into binary. As usual, I will pack the first four with pack('H', var)(unsigned short, 16-bit), then pack the last one with pack('B', var)(unsigned char, 8-bit).

so I will cost 72 bits:

16 * 4 + 8 = 72

I am facing a special situation: my storage is very very precious, I just need 40 bits:

4 * 9 + 1 * 4

I waste 32 bits, and also these 32 bits can be important to me, because I have a lot of data to pack, every time I waste 32 bits, at last, my storage complains to me.

In fact, I can change 4 9-bit variable and 1 4-bit variable into 5 8-bit variable(unsigned char), then I pack them all with pack('B', var), of course I save 32 bits.

4 * 9 + 1 * 4 == 5 * 8

How can I simply change pack 4 9-bit variable and 1 4-bit variable int 5 8-bit variable?

too honest for this site
  • 12,050
  • 4
  • 30
  • 52
roger
  • 9,063
  • 20
  • 72
  • 119

1 Answers1

2

Pack them yourself:

import struct
ninebits = [0b110011001,0b000000000,0b111111111,0b010101010]
fourbit = 0b1010
pack = 0
for i,v in enumerate(ninebits):
    pack <<= 9
    pack |= v
pack <<= 4
pack |= fourbit
print('{:040b}'.format(pack))
print('{:010X}'.format(pack))
print(struct.pack('>LB',pack >> 8, pack & 0xFF))

Output:

1100110010000000001111111110101010101010
CC803FEAAA
b'\xcc\x80?\xea\xaa'

Note that ? is ASCII for \x3f.

Mark Tolonen
  • 166,664
  • 26
  • 169
  • 251
  • I don't think that it is doable directly with `pack` without going through the shift and adding process you put in the `for` loop?...I'm just trying to figure out a way for that...:P...but nevertheless, great answer +1 – Iron Fist Mar 29 '16 at 15:55