Python
Programming
Binary Conversion
Data Types
Coding Techniques

Convert int to binary string in Python

Master System Design with Codemia

Enhance your system design skills with over 120 practice problems, detailed solutions, and hands-on exercises.

Introduction

The fastest way to convert an integer to a binary string in Python is bin(n), which returns a string like '0b101101'. For a cleaner output without the 0b prefix, use format(n, 'b') or the equivalent f-string f'{n:b}'. For fixed-width binary with leading zeros, use a width specifier like f'{n:08b}'. This article covers all the built-in approaches, negative number handling, two's complement conversion, and manual implementations for learning purposes.

Built-In Methods

Python provides three built-in ways to convert an integer to its binary representation. They differ only in formatting.

python
1number = 45
2
3# bin() includes the 0b prefix
4print(bin(number))          # '0b101101'
5
6# format() returns clean digits
7print(format(number, 'b'))  # '101101'
8
9# f-string equivalent
10print(f'{number:b}')        # '101101'

When to Use Each

MethodOutputBest For
bin(n)'0b101101'Debugging, REPL inspection, when prefix is expected
format(n, 'b')'101101'String building, logging, display
f'{n:b}''101101'Inline string formatting

All three handle arbitrarily large integers because Python integers have no fixed bit width.

Fixed Width with Leading Zeros

When displaying byte values, bit masks, or protocol fields, you typically need a fixed number of digits:

python
1value = 13
2
3# 8-bit representation
4print(f'{value:08b}')       # '00001101'
5
6# 16-bit representation
7print(f'{value:016b}')      # '0000000000001101'
8
9# 32-bit representation
10print(f'{value:032b}')      # '00000000000000000000000000001101'

The format specifier 08b means: pad with zeros to 8 characters wide, format as binary. This is more readable and reliable than manually prepending zeros with zfill():

python
1# Works, but less clear than the format specifier
2print(bin(13)[2:].zfill(8))  # '00001101'
3
4# Preferred: the intent is obvious
5print(f'{13:08b}')           # '00001101'

Negative Numbers

This is where most developers get confused. Python integers are arbitrary precision, so there is no fixed bit width. bin(-5) returns the sign plus the magnitude, not a two's complement pattern:

python
print(bin(-5))          # '-0b101'
print(format(-5, 'b'))  # '-101'

Two's Complement Conversion

If you need a fixed-width two's complement representation (the way hardware actually stores negative integers), you must mask the value to the desired width:

python
1value = -5
2
3# 8-bit two's complement
4as_byte = value & 0xFF
5print(f'{as_byte:08b}')    # '11111011'
6
7# 16-bit two's complement
8as_word = value & 0xFFFF
9print(f'{as_word:016b}')   # '1111111111111011'
10
11# 32-bit two's complement
12as_dword = value & 0xFFFFFFFF
13print(f'{as_dword:032b}')  # '11111111111111111111111111111011'

The bitwise AND with a mask (0xFF for 8 bits, 0xFFFF for 16 bits) forces Python to produce the two's complement representation at that width.

Converting Two's Complement Back to Signed

To interpret a two's complement binary string as a signed integer:

python
1def twos_complement_to_int(binary_str: str) -> int:
2    """Convert a two's complement binary string to a signed integer."""
3    width = len(binary_str)
4    value = int(binary_str, 2)
5    if value >= (1 << (width - 1)):
6        value -= (1 << width)
7    return value
8
9print(twos_complement_to_int('11111011'))  # -5
10print(twos_complement_to_int('00001101'))  #  13

Converting Binary Strings Back to Integers

The built-in int() function parses binary strings:

python
1# With 0b prefix
2print(int('0b101101', 2))   # 45
3
4# Without prefix
5print(int('101101', 2))     # 45
6
7# With leading zeros
8print(int('00101101', 2))   # 45
9
10# Using int() with base 0 auto-detects prefix
11print(int('0b101101', 0))   # 45

The second argument specifies the base. Use 2 for binary, 8 for octal, 16 for hexadecimal.

Manual Conversion: Division Method

For understanding the algorithm behind binary conversion, the repeated division method builds the binary string from least significant to most significant bit:

python
1def int_to_binary(n: int) -> str:
2    """Convert a non-negative integer to binary using repeated division."""
3    if n == 0:
4        return '0'
5
6    bits = []
7    value = n
8    while value > 0:
9        bits.append(str(value % 2))
10        value //= 2
11
12    return ''.join(reversed(bits))
13
14print(int_to_binary(45))   # '101101'
15print(int_to_binary(0))    # '0'
16print(int_to_binary(255))  # '11111111'

Each iteration extracts the remainder when dividing by 2 (the current least significant bit), then integer-divides by 2 to shift right. The bits are collected in reverse order and then reversed at the end.

Manual Conversion: Bitwise Method

The same conversion using bitwise operations instead of arithmetic:

python
1def int_to_binary_bitwise(n: int) -> str:
2    """Convert a non-negative integer to binary using bit shifts and masks."""
3    if n == 0:
4        return '0'
5
6    bits = []
7    value = n
8    while value:
9        bits.append(str(value & 1))  # Extract lowest bit
10        value >>= 1                  # Shift right by 1
11
12    return ''.join(reversed(bits))
13
14print(int_to_binary_bitwise(45))   # '101101'

This version is logically identical to the division method but uses & 1 (bitwise AND) instead of % 2 and >>= 1 (right shift) instead of //= 2. Many developers find this version more intuitive when thinking about binary operations.

Practical Applications

Displaying Bit Flags

python
1# Unix file permissions
2permission = 0o755
3print(f'rwx pattern: {permission:09b}')  # '111101101'
4
5# Feature flags
6flags = 0b1010
7features = ['logging', 'metrics', 'tracing', 'alerts']
8for i, feature in enumerate(features):
9    enabled = bool(flags & (1 << (len(features) - 1 - i)))
10    print(f'{feature}: {"on" if enabled else "off"}')

Network Subnet Masks

python
1def display_subnet(mask: int) -> str:
2    """Display an IPv4 subnet mask in both dotted-decimal and binary."""
3    octets = [(mask >> (8 * i)) & 0xFF for i in range(3, -1, -1)]
4    decimal = '.'.join(str(o) for o in octets)
5    binary = '.'.join(f'{o:08b}' for o in octets)
6    return f'{decimal}  ({binary})'
7
8print(display_subnet(0xFFFFFF00))
9# 255.255.255.0  (11111111.11111111.11111111.00000000)
10
11print(display_subnet(0xFFFFF000))
12# 255.255.240.0  (11111111.11111111.11110000.00000000)

Byte Inspection

python
1data = b'Hi'
2for byte in data:
3    print(f'{byte:#010b}  ({chr(byte)})')
4# 0b01001000  (H)
5# 0b01101001  (i)

The # flag in the format specifier adds the 0b prefix, and 010 pads to 10 characters total (including the 0b).

Comparison with Other Bases

Python's format specifiers handle all common bases:

python
1n = 255
2
3print(f'Binary:      {n:b}')     # '11111111'
4print(f'Octal:       {n:o}')     # '377'
5print(f'Decimal:     {n:d}')     # '255'
6print(f'Hexadecimal: {n:x}')     # 'ff'
7print(f'Hex (upper): {n:X}')     # 'FF'
8
9# With prefixes
10print(f'Binary:      {n:#b}')    # '0b11111111'
11print(f'Octal:       {n:#o}')    # '0o377'
12print(f'Hex:         {n:#x}')    # '0xff'

Common Pitfalls

The most common mistake is forgetting that bin() includes the 0b prefix. Comparing bin(45) directly to '101101' returns False because the actual value is '0b101101'. Use format(n, 'b') when you need bare digits.

Expecting bin(-5) to return a two's complement pattern is another frequent error. Python integers are arbitrary precision, so there is no fixed-width machine representation. Mask with & 0xFF or similar to get two's complement at a specific width.

Treating the binary string as a number instead of text leads to bugs. f'{13:08b}' returns the string '00001101', not the integer 1101. If you need to do arithmetic, convert back with int('00001101', 2).

Writing manual conversion functions when the built-in tools already handle the job adds unnecessary complexity and potential bugs. The format() function and f-strings are well-tested and cover all standard use cases. Reserve manual implementations for educational contexts.

Forgetting to specify a width when displaying byte-level data makes output hard to read. format(5, 'b') returns '101', which is correct but ambiguous when you expect 8-bit alignment. Always use '08b' or similar when the bit width matters.

Summary

  • Use bin(n) for quick inspection with the 0b prefix.
  • Use format(n, 'b') or f'{n:b}' for clean binary digit strings without the prefix.
  • Add a width specifier like '08b' for fixed-width output with leading zeros.
  • Mask negative values to a specific width (value & 0xFF) for two's complement representation.
  • Convert binary strings back to integers with int(binary_str, 2).
  • Prefer built-in formatting tools over manual conversion in production code.

Course illustration
Course illustration

All Rights Reserved.