232

I'm trying to convert an integer to binary using the bin() function in Python. However, it always removes the leading zeros, which I actually need, such that the result is always 8-bit:

Example:

bin(1) -> 0b1

# What I would like:
bin(1) -> 0b00000001

Is there a way of doing this?

martineau
  • 119,623
  • 25
  • 170
  • 301
Niels Sønderbæk
  • 3,487
  • 4
  • 30
  • 43
  • See also: [Python int to binary?](http://stackoverflow.com/q/699866/562769), especially [my answer](http://stackoverflow.com/a/21732313/562769) with the n-bit representation. Not exactly the same, but I came to this question searching my answer... – Martin Thoma Apr 10 '16 at 20:20

11 Answers11

338

Use the format() function:

>>> format(14, '#010b')
'0b00001110'

The format() function simply formats the input following the Format Specification mini language. The # makes the format include the 0b prefix, and the 010 size formats the output to fit in 10 characters width, with 0 padding; 2 characters for the 0b prefix, the other 8 for the binary digits.

This is the most compact and direct option.

If you are putting the result in a larger string, use an formatted string literal (3.6+) or use str.format() and put the second argument for the format() function after the colon of the placeholder {:..}:

>>> value = 14
>>> f'The produced output, in binary, is: {value:#010b}'
'The produced output, in binary, is: 0b00001110'
>>> 'The produced output, in binary, is: {:#010b}'.format(value)
'The produced output, in binary, is: 0b00001110'

As it happens, even for just formatting a single value (so without putting the result in a larger string), using a formatted string literal is faster than using format():

>>> import timeit
>>> timeit.timeit("f_(v, '#010b')", "v = 14; f_ = format")  # use a local for performance
0.40298633499332936
>>> timeit.timeit("f'{v:#010b}'", "v = 14")
0.2850222919951193

But I'd use that only if performance in a tight loop matters, as format(...) communicates the intent better.

If you did not want the 0b prefix, simply drop the # and adjust the length of the field:

>>> format(14, '08b')
'00001110'
ruohola
  • 21,987
  • 6
  • 62
  • 97
Martijn Pieters
  • 1,048,767
  • 296
  • 4,058
  • 3,343
  • 5
    Exactly what I was looking for, this formatting is really helpful to me. I have started learning bit manipulation and I was googling for bit formatting for numbers in Python. Found this. Thank you. – kratostoical Dec 17 '17 at 13:23
  • Works nice. Can get a bit bulky though. `format(192,'08b')+'.'+format(0,'08b')+'.'+format(2,'08b')+'.'+format(33,'08b')` `11000000.00000000.00000010.00100001` – voices May 11 '19 at 17:34
  • @tjt263: That's why I explicitly state that *If you are putting the result in a larger string, use an formatted string literal (3.6+) or use `str.format()` and put the second argument for the format() function after the colon of the placeholder `{:..}`:* – Martijn Pieters May 11 '19 at 19:32
  • 2
    @tjt263: e.g. use `f"{192:08b}.{0:08b}.{2:08b}.{33:08b}"`. – Martijn Pieters May 11 '19 at 19:33
  • Very nice. I never would have known that's what you meant from explanation alone. But now I've seen your example, I'll probably never forget it. Cheers. – voices May 11 '19 at 20:04
  • @MartijnPieters what if I want the number of bits variable? For example you have used ```format(14, '08b')``` but instead of 8, I need variable x there. – efe373 Jan 18 '23 at 09:09
  • @efe373: you can format the second argument, it's just a string. E.g. `format(14, f"0{x}b")`. Or combine it into a single format string, `f"{14:0{x}b}"`. – Martijn Pieters Jan 22 '23 at 16:03
143
>>> '{:08b}'.format(1)
'00000001'

See: Format Specification Mini-Language


Note for Python 2.6 or older, you cannot omit the positional argument identifier before :, so use

>>> '{0:08b}'.format(1)
'00000001'      
Josselin
  • 2,593
  • 2
  • 22
  • 35
bwbrowning
  • 6,200
  • 7
  • 31
  • 36
  • 3
    There is no need to use `str.format()` here when `format()` will do. You are missing the `0b` prefix. – Martijn Pieters Jun 04 '13 at 19:55
  • 2
    @MartijnPieters, `str.format` is more flexible than `format()` because it will allow you to do multiple variables at once. I keep forgetting that the `format` function even exists. Admittedly it's perfectly adequate in this case. – Mark Ransom Jun 04 '13 at 22:18
  • 1
    @MarkRansom: Exactly, when you are only using `str.format()` with just one `{}` element, no other text, you are *not* using string templating, you are formatting *one value*. In that case just use `format()`. :-) – Martijn Pieters Jun 04 '13 at 22:19
  • This does not work anymore: print("TCP: Option: Data: {:08b}".format(option_data)) TypeError: unsupported format string passed to tuple.__format__ – wheeler Mar 10 '21 at 03:43
46

I am using

bin(1)[2:].zfill(8)

will print

'00000001'
rekinyz
  • 6,576
  • 2
  • 29
  • 32
11

When using Python >= 3.6, you can use f-strings with string formatting:

>>> var = 23
>>> f"{var:#010b}"
'0b00010111'

Explanation:

  • var the variable to format
  • : everything after this is the format specifier
  • # use the alternative form (adds the 0b prefix)
  • 0 pad with zeros
  • 10 pad to a total length off 10 (this includes the 2 chars for 0b)
  • b use binary representation for the number
ruohola
  • 21,987
  • 6
  • 62
  • 97
  • 1
    No, it is not the cleanest, *not unless you do more with the string than just a single placeholder*. Otherwise `format(var, "#010b")` communicates *intent* much better. It is, however, the fastest option. But you know that already, right, because I already cover *all of what you posted* in my answer. – Martijn Pieters Feb 28 '20 at 02:05
  • I agree @MartijnPieters, `format` is cleaner if you don't need it as part of a longer string. – ruohola Jul 29 '22 at 12:32
10

You can use the string formatting mini language (Thanks to @Martijn Pieters for the suggestion) idea:

def binary(num, length=8):
    return format(num, '#0{}b'.format(length + 2))

Demo:

print(binary(1))

Output:

'0b00000001'
Neuron
  • 5,141
  • 5
  • 38
  • 59
Peter Varo
  • 11,726
  • 7
  • 55
  • 77
  • 2
    The same formatting language can be used to include the prefix for you. Use `#`. There is also `format()`, which saves you having to do a full string template. – Martijn Pieters Jun 04 '13 at 19:57
5

I like python f-string formatting for a little more complex things like using a parameter in format:

>>> x = 5
>>> n = 8
>>> print(f"{x:0{n}b}")
00000101

Here I print variable x with following formatting: I want it to be left-filled with 0 to have length = n, in b (binary) format. See Format Specification Mini-Language from previous answers for more.

Rustam A.
  • 809
  • 8
  • 15
3

Sometimes you just want a simple one liner:

binary = ''.join(['{0:08b}'.format(ord(x)) for x in input])

Python 3

Mark
  • 556
  • 8
  • 12
  • 2
    Note that the `[ ]` shouldn't be needed - `join()` accepts a generator expression. `''.join('{0:08b}'.format(ord(x)) for x in input)` – Christoph Burschka Dec 02 '17 at 13:39
  • 2
    @ChristophBurschka note that because `str.join()` needs to make two passes, a generator input is first converted to a list before joining. This takes a bit of a toll on performance and do it’s actually *better* here to pass in a list comprehension rather than a generator expression. It’s one if them exceptions to the rule. – Martijn Pieters Feb 28 '20 at 02:01
0

While many solutions have been posted here and there the fastest way (if you don't need the '0b' part in front) is combining f'{x:'b'}' with .zfill(n) for padding.

Even if you want the leading '0b' you can add it by using the following code:

'0b'+f'{i:b}'.zfill(n)

And it is still faster and more readable than using the f"{x:0{n}b}" method

Find relevant benchmarking code and results here

-1

You can use something like this

("{:0%db}"%length).format(num)
Muds
  • 4,006
  • 5
  • 31
  • 53
Adam
  • 7
  • 1
  • 2
    Please at least use code block for your code snippet. And if you really want it to be a good answer, then also add some comments on why this solution is solving OP question. – β.εηοιτ.βε Mar 31 '15 at 16:18
  • You don’t need to use a different string formatting style just to add a variable width. Just add another placeholder: `"{:0{l}b}".format(num, l=length)` – Martijn Pieters Feb 28 '20 at 01:59
-3

You can use zfill:

print str(1).zfill(2) 
print str(10).zfill(2) 
print str(100).zfill(2)

prints:

01
10
100

I like this solution, as it helps not only when outputting the number, but when you need to assign it to a variable... e.g. - x = str(datetime.date.today().month).zfill(2) will return x as '02' for the month of feb.

Anshul Garg
  • 313
  • 1
  • 3
  • 14
  • 1
    problem with zfill is it treats the binary string like a string and adds the zeros before the binary 'b' indicator... eg `bin(14)` gives ` '0b1110' ` and `bin(14).zfill(8)` gives ` '000b1110' ` not ` '0b00001110' ` which is whats desired – Shaun Aug 09 '17 at 20:31
-3

You can use string.rjust method:

string.rjust(length, fillchar)

fillchar is optional

and for your Question you can write like this

'0b'+ '1'.rjust(8,'0)

so it will be '0b00000001'

IAbstract
  • 19,551
  • 15
  • 98
  • 146
  • 1
    There is a syntax error. But more importantly, it doesn't answer the question at all, which is about converting an `int` to its textual binary representation; you don't even start with an `int`. – Thierry Lathuille May 30 '20 at 18:13