# Python, how to decode Binary coded decimal (BCD)

Description of the binary field is:

Caller number, expressed with compressed BCD code, and the surplus bits are filled with “0xF”

I have tried to print with struct format `'16c'` and I get: `('3', 'x00', 'x02', 'x05', 'x15', 'x13', 'G', 'O', 'xff', 'xff', 'xff', 'xff', 'xff', 'xff', 'xff', 'xff')` and if I use `'16b'` i get `(51, 0, 2, 5, 21, 19, 71, 79, -1, -1, -1, -1, -1, -1, -1, -1)`. And it is not correct, I should get phone number, and numbers above are invalid.

```print struct.unpack_from('>16b', str(data.read()),offset=46)
```

Above is code that didn’t work and I get invalid numbers. With what format should I unpack that 16 byte field and how to convert BCD code ?

## Answer

BCD codes work with 4 bits per number, and normally encode only the digits 0 – 9. So each byte in your sequence contains 2 numbers, 1 per 4 bits of information.

The following method uses a generator to produce those digits; I am assuming that a 0xF value means there are no more digits to follow:

```def bcdDigits(chars):
for char in chars:
char = ord(char)
for val in (char >> 4, char & 0xF):
if val == 0xF:
return
yield val
```

Here I use a right-shift operator to move the left-most 4 bits to the right, and a bitwise AND to select just the right-most 4 bits.

Demonstration:

```>>> characters = ('3', 'x00', 'x02', 'x05', 'x15', 'x13', 'G', 'O', 'xff', 'xff', 'xff', 'xff', 'xff', 'xff', 'xff', 'xff')
>>> list(bcdDigits(characters))
[3, 3, 0, 0, 0, 2, 0, 5, 1, 5, 1, 3, 4, 7, 4]
```

The method works with the `c` output; you can skip the `ord` call in the method if you pass integers directly (but use the `B` unsigned variant instead). Alternatively, you could just read those 16 bytes straight from your file and apply this function to those bytes directly without using struct.