Back to Blog
Python

Python bin() Function: Converting Integers to Binary

python bin function: Learn how Python's bin() function converts integers to binary strings, handles negative values, and compares with format() for practical bit-level...

bin()Python built-insbit manipulationbinary conversioninteger formatting
Illustration of the Python bin() function converting an integer into its binary string representation with the 0b prefix.

The python bin function converts an integer into its binary string representation with a 0b prefix. It is a built-in that appears in bit manipulation code, protocol debugging, and anywhere a developer needs to inspect the bits behind a number. Understanding exactly what it returns, and what it does not return, prevents the subtle bugs that appear when binary output is parsed or compared.

What the bin() Function Returns

bin() takes an integer and returns a string. The string starts with 0b, followed by the binary digits.

>>> bin(10) '0b1010'

The 0b prefix is part of the return value, not a display artifact. Any code that strips it, parses it, or compares it must account for the prefix explicitly.

The function accepts any integer, including zero and negative values:

>>> bin(0) '0b0' >>> bin(255) '0b11111111'

For positive integers, the result is the standard base-2 representation with no leading zeros beyond the first significant bit.

Syntax and the index Protocol

The signature is simple: bin(x). The argument must be an integer, or an object that implements the __index__ method. This is a common source of confusion because objects that implement __int__ but not __index__ will raise a TypeError.

>>> bin(3.5) Traceback (most recent call last): File "<stdin>", line 1, in <module> TypeError: 'float' object cannot be interpreted as an integer

A custom class that defines __index__ works:

class BitMask: def __init__(self, value): self.value = value def __index__(self): return self.value >>> bin(BitMask(6)) '0b110'

The __index__ requirement exists because bin() needs a true integer, not a value that merely converts to one. This distinguishes it from functions like int() that accept a broader range of inputs.

How bin() Handles Negative Numbers

Negative integers return a string with a minus sign before the 0b prefix:

>>> bin(-5) '-0b101'

The result is not two's complement. It is the binary representation of the absolute value, prefixed with a minus sign. This surprises developers who expect bin(-5) to show the two's complement bit pattern used internally by the CPU.

If the actual two's complement representation is needed, it must be constructed manually:

def twos_complement(value, bits): if value >= 0: return bin(value & ((1 << bits) - 1)) return bin((1 << bits) + value) >>> twos_complement(-5, 8) '0b11111011'

The masking approach works because bitwise operations in Python operate on the infinite two's complement representation of negative integers. Masking with (1 << bits) - 1 truncates that infinite pattern to the desired width.

Removing the 0b Prefix

When the prefix is not wanted, slicing works:

>>> bin(42)[2:] '101010'

The format() built-in provides the same result without slicing:

>>> format(42, 'b') '101010'

format() also supports zero-padding, which is useful when a fixed-width binary string is required:

>>> format(42, '08b') '00101010'

For fixed-width output, format() is the clearer choice. Slicing bin() output works but leaves the padding logic to the caller.

Practical Use Cases for bin()

Binary representation is useful when inspecting bit flags. A configuration value that packs several boolean options into a single integer becomes readable when converted:

flags = 0b1011 readable = bin(flags) # '0b1011' -> bit 0 set, bit 1 set, bit 2 clear, bit 3 set

During protocol debugging, converting received bytes to binary helps identify which bits carry which fields. The same applies when verifying that a bitmask was constructed correctly:

mask = (1 << 3) | (1 << 5) print(bin(mask)) # '0b101000'

bin() is also a teaching tool for understanding how bitwise operators behave. Seeing the intermediate results of shifts, ANDs, and ORs in binary form makes the operation explicit.

bin() vs format() for Binary Conversion

Both produce binary strings, but they differ in the prefix and in padding support:

Function callResult
bin(10)'0b1010'
format(10, 'b')'1010'
format(10, '#b')'0b1010'
format(10, '08b')'00001010'

The # flag in format() adds the 0b prefix, matching bin() output. When the prefix is required, either bin() or format(x, '#b') works. When it is not, format(x, 'b') avoids the slice.

The choice between them is mostly stylistic. bin() is the shorter call when the prefix is desired. format() is more flexible when width or padding matters.

Performance and Runtime Considerations

bin() allocates a new string on every call. The length of that string grows with the number of bits in the integer. For a 64-bit integer, the result is about 66 characters including the prefix. For a 1024-bit integer, it is over 300 characters.

In a hot loop that converts the same value repeatedly, caching the string avoids redundant allocation:

cache = {value: bin(value) for value in relevant_values}

For one-off conversions, this caching is unnecessary. The cost of bin() is proportional to the bit length, so it is cheap for typical integers and only becomes noticeable when converting very large numbers in bulk.

There is no meaningful performance difference between bin() and format() for the same output. Both go through the same internal conversion path. Choose based on readability, not speed.

Edge Cases and Common Mistakes

The most frequent mistake is assuming bin() accepts anything that int() accepts. Floats and strings raise TypeError:

>>> bin("1010") Traceback (most recent call last): File "<stdin>", line 1, in <module> TypeError: 'str' object cannot be interpreted as an integer

Another mistake is forgetting that the 0b prefix is part of the string. Comparing bin(10) == '1010' fails silently. Use format(10, 'b') or strip the prefix before comparison.

A third issue appears when parsing binary strings back to integers. The int() function accepts the 0b prefix, but only when the base is explicitly 0 or 2:

>>> int('0b1010', 0) 10 >>> int('0b1010', 2) 10

Passing base 10, which is the default, raises ValueError because 0b is not a valid decimal digit sequence. This round-trip behavior is worth remembering when binary strings cross system boundaries.

python bin function: Practical Usage and Code Examples | RYUSLOG DEV