Bitwise operations work directly on the binary representations of numbers (or other data). Instead of treating numbers as numerical values, we manipulate their individual bits (0s and 1s). These operations are fast, low-level, and super useful in scenarios like:
- Optimizing code for performance.
- Working with hardware, networking, or cryptography.
- Manipulating flags, permissions, or pixel data in images.
Python provides six main bitwise operators: AND, OR, XOR, NOT, Left Shift, and Right Shift. Let’s learn each one with examples.
Before we jump into the operators, you need to know how numbers are represented in binary. For example:
- The number
5in binary is0101. - The number
3in binary is0011.
Each digit in a binary number is a bit. The rightmost bit is the least significant bit (LSB), and the leftmost is the most significant bit (MSB).
You can convert integers to binary in Python using the bin() function:
print(bin(5)) # Output: 0b101 (0b indicates binary)
print(bin(3)) # Output: 0b11Let’s explore each bitwise operator, what it does, and how to use it in Python.
- What it does: Compares each bit of two numbers. If both bits are
1, the result is1; otherwise, it’s0. - Use case: Masking (selecting specific bits) or checking if certain bits are set.
Example:
a = 5 # 0101
b = 3 # 0011
result = a & b # 0101 & 0011 = 0001
print(result) # Output: 1How it works:
0101 (5)
& 0011 (3)
-------
0001 (1)
- What it does: Compares each bit of two numbers. If at least one bit is
1, the result is1; otherwise, it’s0. - Use case: Setting specific bits or combining flags.
Example:
a = 5 # 0101
b = 3 # 0011
result = a | b # 0101 | 0011 = 0111
print(result) # Output: 7How it works:
0101 (5)
| 0011 (3)
-------
0111 (7)
- What it does: Compares each bit of two numbers. If the bits are different (one is
1, the other is0), the result is1; otherwise, it’s0. - Use case: Toggling bits, encryption, or finding unique elements.
Example:
a = 5 # 0101
b = 3 # 0011
result = a ^ b # 0101 ^ 0011 = 0110
print(result) # Output: 6How it works:
0101 (5)
^ 0011 (3)
-------
0110 (6)
Fun Fact: XORing a number with itself gives 0, and XORing a number with 0 gives the number itself.
- What it does: Flips all the bits of a number (
0becomes1,1becomes0). In Python, this is equivalent to-(x + 1)due to how negative numbers are represented (two’s complement). - Use case: Inverting bits or computing complements.
Example:
a = 5 # 0101
result = ~a # ~0101 = ...11111010 (in two’s complement, this is -6)
print(result) # Output: -6Explanation:
- For a number
x,~x = -(x + 1). - So,
~5 = -(5 + 1) = -6.
- What it does: Shifts all bits of a number to the left by a specified number of positions. Zeros are filled in from the right. This is equivalent to multiplying by
2^n(wherenis the shift amount). - Use case: Fast multiplication or aligning bits.
Example:
a = 5 # 0101
result = a << 2 # 0101 << 2 = 010100 (shift left by 2)
print(result) # Output: 20How it works:
0101 << 2 = 010100
5 * (2^2) = 5 * 4 = 20
- What it does: Shifts all bits of a number to the right by a specified number of positions. For positive numbers, zeros are filled in from the left. This is equivalent to dividing by
2^n(integer division). - Use case: Fast division or extracting specific bits.
Example:
a = 20 # 10100
result = a >> 2 # 10100 >> 2 = 00101
print(result) # Output: 5How it works:
10100 >> 2 = 00101
20 // (2^2) = 20 // 4 = 5
Let’s apply bitwise operations to solve some real-world problems.
- A number is even if its least significant bit (LSB) is
0, and odd if it’s1. - We can use
&with1to check the LSB.
def is_even(n):
return (n & 1) == 0
print(is_even(4)) # True (4 is 100, LSB is 0)
print(is_even(7)) # False (7 is 111, LSB is 1)- XOR can be used to swap values efficiently.
a = 5 # 0101
b = 3 # 0011
a ^= b # a = 0101 ^ 0011 = 0110
b ^= a # b = 0011 ^ 0110 = 0101
a ^= b # a = 0110 ^ 0101 = 0011
print(a, b) # Output: 3 5- Use
|to set a bit (turn it to1) and&with~to clear a bit (turn it to0).
# Set the 2nd bit (position 1, counting from 0)
number = 8 # 1000
mask = 1 << 1 # 0010
number |= mask # 1000 | 0010 = 1010
print(number) # Output: 10
# Clear the 3rd bit (position 2)
number = 12 # 1100
mask = ~(1 << 2) # ~(0100) = ...1011
number &= mask # 1100 & 1011 = 1000
print(number) # Output: 8- Count the number of
1bits in a number’s binary representation.
def count_set_bits(n):
count = 0
while n:
count += n & 1 # Check LSB
n >>= 1 # Shift right
return count
print(count_set_bits(13)) # 13 = 1101, Output: 3