Convert hex to binary

403,812

Solution 1

For solving the left-side trailing zero problem:


my_hexdata = "1a"

scale = 16 ## equals to hexadecimal

num_of_bits = 8

bin(int(my_hexdata, scale))[2:].zfill(num_of_bits)

It will give 00011010 instead of the trimmed version.

Solution 2

import binascii

binary_string = binascii.unhexlify(hex_string)

Read

binascii.unhexlify

Return the binary data represented by the hexadecimal string specified as the parameter.

Solution 3

Convert hex to binary

I have ABC123EFFF.

I want to have 001010101111000001001000111110111111111111 (i.e. binary repr. with, say, 42 digits and leading zeroes).

Short answer:

The new f-strings in Python 3.6 allow you to do this using very terse syntax:

>>> f'{0xABC123EFFF:0>42b}'
'001010101111000001001000111110111111111111'

or to break that up with the semantics:

>>> number, pad, rjust, size, kind = 0xABC123EFFF, '0', '>', 42, 'b'
>>> f'{number:{pad}{rjust}{size}{kind}}'
'001010101111000001001000111110111111111111'

Long answer:

What you are actually saying is that you have a value in a hexadecimal representation, and you want to represent an equivalent value in binary.

The value of equivalence is an integer. But you may begin with a string, and to view in binary, you must end with a string.

Convert hex to binary, 42 digits and leading zeros?

We have several direct ways to accomplish this goal, without hacks using slices.

First, before we can do any binary manipulation at all, convert to int (I presume this is in a string format, not as a literal):

>>> integer = int('ABC123EFFF', 16)
>>> integer
737679765503

alternatively we could use an integer literal as expressed in hexadecimal form:

>>> integer = 0xABC123EFFF
>>> integer
737679765503

Now we need to express our integer in a binary representation.

Use the builtin function, format

Then pass to format:

>>> format(integer, '0>42b')
'001010101111000001001000111110111111111111'

This uses the formatting specification's mini-language.

To break that down, here's the grammar form of it:

[[fill]align][sign][#][0][width][,][.precision][type]

To make that into a specification for our needs, we just exclude the things we don't need:

>>> spec = '{fill}{align}{width}{type}'.format(fill='0', align='>', width=42, type='b')
>>> spec
'0>42b'

and just pass that to format

>>> bin_representation = format(integer, spec)
>>> bin_representation
'001010101111000001001000111110111111111111'
>>> print(bin_representation)
001010101111000001001000111110111111111111

String Formatting (Templating) with str.format

We can use that in a string using str.format method:

>>> 'here is the binary form: {0:{spec}}'.format(integer, spec=spec)
'here is the binary form: 001010101111000001001000111110111111111111'

Or just put the spec directly in the original string:

>>> 'here is the binary form: {0:0>42b}'.format(integer)
'here is the binary form: 001010101111000001001000111110111111111111'

String Formatting with the new f-strings

Let's demonstrate the new f-strings. They use the same mini-language formatting rules:

>>> integer = 0xABC123EFFF
>>> length = 42
>>> f'{integer:0>{length}b}'
'001010101111000001001000111110111111111111'

Now let's put this functionality into a function to encourage reusability:

def bin_format(integer, length):
    return f'{integer:0>{length}b}'

And now:

>>> bin_format(0xABC123EFFF, 42)
'001010101111000001001000111110111111111111'    

Aside

If you actually just wanted to encode the data as a string of bytes in memory or on disk, you can use the int.to_bytes method, which is only available in Python 3:

>>> help(int.to_bytes)
to_bytes(...)
    int.to_bytes(length, byteorder, *, signed=False) -> bytes
...

And since 42 bits divided by 8 bits per byte equals 6 bytes:

>>> integer.to_bytes(6, 'big')
b'\x00\xab\xc1#\xef\xff'

Solution 4

bin(int("abc123efff", 16))[2:]

Solution 5

>>> bin( 0xABC123EFFF )

'0b1010101111000001001000111110111111111111'

Share:
403,812
Russia Must Remove Putin
Author by

Russia Must Remove Putin

Dear Russian People Vladimir Putin has not only invaded Ukraine, but he has begun an assault on the people in Ukraine's capital, Kiev. Ukraine is viewed by the international community as entirely the victim in the current situation. The entire free world is lining up against you. Now imagine what is happening in Kiev as happening in Moscow - but instead of sending poorly armed and trained children to die, they are just sending missiles and bombs of all sizes. To prevent this from happening, you must take to the streets or any channel you have the most influence with, and do everything in your power to contribute to the removal of Vladimir Putin. Warmly and Sincerely, Aaron Hall Russian Translation via Google Translate: Дорогие русские люди Владимир Путин не только вторгся в Украину, но и начал наступление на людей в столице Украины Киеве. Украина рассматривается международным сообществом исключительно как жертва сложившейся ситуации. Весь свободный мир выстраивается против вас. А теперь представьте, что происходит в Киеве, как это происходит в Москве - только вместо того, чтобы посылать на смерть плохо вооруженных и обученных детей, они просто посылают ракеты и бомбы всех размеров. Чтобы этого не произошло, вы должны выйти на улицу или на любой канал, на который вы имеете наибольшее влияние, и сделать все, что в ваших силах, чтобы способствовать смещению Владимира Путина. Тепло и искренне, Aaron Hall

Updated on July 21, 2021

Comments

  • Russia Must Remove Putin
    Russia Must Remove Putin almost 3 years

    I have ABC123EFFF.

    I want to have 001010101111000001001000111110111111111111 (i.e. binary repr. with, say, 42 digits and leading zeroes).

    How?

    • hola
      hola over 3 years
      I have ABC123EFFF -- ABC123EFFF is a string or number (i.e., 0xABC123EFFF)?
    • buzz
      buzz about 3 years
      If it is a string, this lambda I found online years ago might be helpful: binary = lambda x: "".join(reversed( [i+j for i,j in zip( *[ ["{0:04b}".format(int(c,16)) for c in reversed("0"+x)][n::2] for n in [1,0] ] ) ] )) binary("ABC123EFFF") '1010101111000001001000111110111111111111' Also works for leading zeros.
  • pavium
    pavium over 14 years
    Or replace each pair of hex digits with the corresponding 8 binary digits, or replace each triplet of hex digits with the corresponding 12 binary digits ... or replace each 10 hex digits, with the corresponding 40 binary digits - Oops! back where we started!
  • pavium
    pavium over 14 years
    docs.python.org/library/binascii.html is subtitled Convert between binary and ASCII. Doesn't that mean it returns a string?
  • Matt Good
    Matt Good over 14 years
    Yes, it returns a string containing the bytes represented, e.g. >>> unhexlify("ab") "\xab"
  • Matt Good
    Matt Good over 14 years
    If the input is "1a" this gives "11010", not "00011010" which may or may not be what you want.
  • Scott Griffiths
    Scott Griffiths over 14 years
    It's quite reasonable to need the leading zeros (and to not need them). You might want the null byte 0x00 to be eight zero bits for example - this is important for some applications. Also the OP has a leading zero in his example (but I suspect that's just random in this case!)
  • mikemaccana
    mikemaccana over 14 years
    This fails if hex_string is set to 'f0'
  • Sufian
    Sufian about 9 years
    Where's the description/explanation?
  • Edd
    Edd about 9 years
    Calculation for the number of bits is len(my_hexdata) * log2(scale).
  • David 天宇 Wong
    David 天宇 Wong almost 9 years
    Any idea how to return "001010100" ?
  • Goodies
    Goodies over 8 years
    I know this is old, but what exactly is the point of the "and 1"?
  • John Montgomery
    John Montgomery over 8 years
    It's for the old days of python before the ternary operator. The (n & (1 << i)) will either return zero or something other than zero. We only want a one or zero, so that "and 1" is there to ensure that.
  • Dragon
    Dragon over 6 years
    Doesn't provide leading zeros if hex string starts with 00.
  • Dragon
    Dragon over 6 years
    Doesn't provide leading zeros if hex string starts with 00.
  • Dragon
    Dragon over 6 years
    Doesn't provide leading zeros if hex string starts with 00.
  • Edison
    Edison about 6 years
    This script worked best for me to convert a crypto private key in hex to binary for testing purposes. Does anyone know how to split the binary string into 8 bit chunks and print it out? i.e. 01111001 11111110.
  • miracle173
    miracle173 almost 5 years
    works only if hex_string has an even number of hexadecimal digits
  • DeanM
    DeanM almost 5 years
    @Dragon myhex = '1A' bin(int(myhex, 16))[2:].zfill(8) >>> '00011010' zhex = '00' bin(int(zhex, 16))[2:].zfill(8) >>> '00000000' It appears that this works even when the hex string is '00'.
  • David Glance
    David Glance almost 4 years
    I don't know why this was voted up as it doesn't answer the OP's actual request - see any of the other posts for an answer
  • OneCricketeer
    OneCricketeer almost 3 years
    Don't use string concatenation. return "".join(HEX_TO_BINARY_CONVERSION_TABLE[c] for c in hex_string)
  • arman
    arman almost 3 years
    @DeanM This does not work when you have leading zeros. E.g., you get 01001000 instead of 0000000001001000 when you've zhex='0048'. This answer works for me.
  • Edoardo Vignati
    Edoardo Vignati over 2 years
    Nice. For hex strings instead of hex values: bin_code = bin(int(hex_code, 0))[2:]
  • Stefan
    Stefan over 2 years
    I think you mean bin_code = bin(int(hex_code, 16))[2:]
  • Edoardo Vignati
    Edoardo Vignati over 2 years
    Yes that's right. To clarify my answer: base 0 works if the hex string is prefixed with "0x"
  • sgowd
    sgowd almost 2 years
    This does not solve the OP's question.