Not sure if there's a better way, but this works (assuming the numbers are always 16-bit):
# Takes a hex-encoded 16-bit number and returns a binary representation with
# leading zeros and underscores as a nibble separator.
def binary_representation(string):
return '0b' + '_'.join(
''.join(nibble) for nibble in zip(*([iter('{:>016b}'.format(int(string, 16)))]*4)))
assert binary_representation('0x1234') == '0b0001_0010_0011_0100'
The zip
trick is a good one that comes from the grouper
example in the Python docs. That call essentially emits [('0', '0', '0', '1'), ('0', '0', '1', '0'), ...]
. From there, you just need to turn each nibble into a single string and then join them all with underscores.
The other interesting bit here is the {:>016b}
format, which gives you a right-aligned, zero-padded binary representation of a number. If you need to support different sizes of numbers, this is the part you'll need to change.
UPDATE
Given that your number starts out as a string, this approach is even simpler, inspired by @Joran's answer but without the lookup table.
def binary_representation(string):
return '0b' + '_'.join(['{:>04b}'.format(int(d, 16)) for d in string[2:]])