Bitwise Operators in Python: Truth Tables, Idioms, and Examples
Learn Python's 6 bitwise operators (AND, OR, XOR, NOT, left shift, right shift) with truth tables, placement idioms, and worked examples verified from first principles.
Python’s six bitwise operators let you manipulate individual bits of an integer, and placement coding rounds test them more often than most students expect.
The operators are & (AND), | (OR), ^ (XOR), ~ (NOT), << (left shift), and >> (right shift). Each works on the binary representation of integers, not on floats. If you try 3.5 & 2, Python raises a TypeError.
The Six Operators at a Glance
| Operator | Symbol | Effect |
|---|---|---|
| AND | & | Sets bit to 1 only if both bits are 1 |
| OR | ` | ` |
| XOR | ^ | Sets bit to 1 if the two bits differ |
| NOT | ~ | Flips every bit; for integer n, result is -(n+1) |
| Left Shift | << | Shifts bits left by k positions; equivalent to multiplying by 2^k |
| Right Shift | >> | Shifts bits right by k positions; equivalent to floor-dividing by 2^k |
Truth Tables for AND, OR, XOR, NOT
AND (&)
| A | B | A & B |
|---|---|---|
| 0 | 0 | 0 |
| 0 | 1 | 0 |
| 1 | 0 | 0 |
| 1 | 1 | 1 |
OR (|)
| A | B | A | B |
|---|---|---------|
| 0 | 0 | 0 |
| 0 | 1 | 1 |
| 1 | 0 | 1 |
| 1 | 1 | 1 |
XOR (^)
| A | B | A ^ B |
|---|---|---|
| 0 | 0 | 0 |
| 0 | 1 | 1 |
| 1 | 0 | 1 |
| 1 | 1 | 0 |
NOT (~)
| A | ~A |
|---|---|
| 0 | 1 |
| 1 | 0 |
For signed integers, ~n equals -(n + 1) because Python uses two’s complement internally.
Worked example:
a = 12 # Binary: 1100
b = 10 # Binary: 1010
print(a & b) # 8 → 1000
print(a | b) # 14 → 1110
print(a ^ b) # 6 → 0110
print(~a) # -13 → -(12 + 1)
Verification from first principles:
12 & 10: 1100 AND 1010 = 1000 = 812 | 10: 1100 OR 1010 = 1110 = 1412 ^ 10: 1100 XOR 1010 = 0110 = 6~12: -(12 + 1) = -13
Shift Operators: << and >>
The left shift operator << moves bits toward higher positions. Each shift left by 1 doubles the value.
x = 5 # Binary: 0101
print(x << 1) # 10 → 1010
print(x << 3) # 40 → 101000
Verification:
5 << 1: 5 * 2^1 = 105 << 3: 5 * 2^3 = 40
The right shift operator >> moves bits toward lower positions. Each shift right by 1 halves the value (floor division).
x = 20 # Binary: 10100
print(x >> 1) # 10 → 1010
print(x >> 2) # 5 → 101
Verification:
20 >> 1: 20 // 2^1 = 1020 >> 2: 20 // 2^2 = 5
For negative numbers, >> floors toward negative infinity:
print(-7 >> 1) # -4 (not -3)
This is because Python’s right shift performs arithmetic shift (preserves sign), and floor(-7 / 2) = -4 per the Python language reference.
Placement Idioms — Worked Examples
Three patterns that appear repeatedly in placement OA rounds.
Check if a Number is a Power of 2
A power of 2 in binary has exactly one set bit: 1, 10, 100, 1000, etc. Subtracting 1 flips that bit and sets all lower bits. AND-ing the original with (original - 1) gives 0.
def is_power_of_two(n):
return n > 0 and (n & (n - 1)) == 0
print(is_power_of_two(16)) # True → 10000 & 01111 = 0
print(is_power_of_two(18)) # False → 10010 & 10001 = 10000 ≠ 0
Verification:
- 16 = 10000; 15 = 01111; 10000 & 01111 = 00000 = 0, so True
- 18 = 10010; 17 = 10001; 10010 & 10001 = 10000 = 16, non-zero, so False
Swap Two Numbers Without a Temp Variable
XOR has the property that a ^ a = 0 and a ^ 0 = a. Three XOR operations swap values in-place.
a, b = 7, 3
a ^= b # a = 7 ^ 3 = 4 (0111 ^ 0011 = 0100)
b ^= a # b = 3 ^ 4 = 7 (0011 ^ 0100 = 0111)
a ^= b # a = 4 ^ 7 = 3 (0100 ^ 0111 = 0011)
print(a, b) # 3, 7
Verification:
- Step 1: a = 0111 XOR 0011 = 0100 = 4
- Step 2: b = 0011 XOR 0100 = 0111 = 7
- Step 3: a = 0100 XOR 0111 = 0011 = 3
Count Set Bits (Brian Kernighan’s Algorithm)
Each iteration of n & (n - 1) clears the lowest set bit. Count iterations until n reaches 0.
def count_set_bits(n):
count = 0
while n:
n &= (n - 1)
count += 1
return count
print(count_set_bits(13)) # 3 → 1101 has three 1-bits
print(count_set_bits(255)) # 8 → 11111111 has eight 1-bits
Verification for n = 13 (binary 1101):
- Iteration 1: 1101 & 1100 = 1100, count = 1
- Iteration 2: 1100 & 1011 = 1000, count = 2
- Iteration 3: 1000 & 0111 = 0000, count = 3
- Loop ends. Answer: 3 set bits.
Operator Precedence
A common pitfall: comparison operators (==, !=) bind tighter than bitwise operators. This means x & 1 == 0 parses as x & (1 == 0), not (x & 1) == 0.
Correct precedence order from highest to lowest:
| Priority | Operator |
|---|---|
| 1 (highest) | ~ (NOT) |
| 2 | <<, >> (shifts) |
| 3 | & (AND) |
| 4 | ^ (XOR) |
| 5 | ` |
| 6 (lowest among bitwise) | Comparison (==, <, >, etc.) binds ABOVE bitwise AND/OR/XOR |
Always use parentheses when combining bitwise operators with comparisons:
# Wrong — parses as x & (1 == 0) → x & False → 0
x = 6
print(x & 1 == 0) # False (unexpected)
# Correct
print((x & 1) == 0) # True (6 is even)
When Placement Papers Test Bitwise Ops
Bitwise questions appear in two forms during campus placements:
- MCQ pattern: given an expression like
12 & 7 | 3, predict the output. These test your knowledge of truth tables plus precedence rules. - Coding pattern: solve an optimisation problem (find the lone non-repeating element, check power of 2, toggle specific bits) where the bitwise solution runs in O(n) or O(1) versus the brute-force O(n log n).
The XOR trick for finding a single non-repeating element in an array is especially popular:
def find_unique(arr):
result = 0
for num in arr:
result ^= num
return result
print(find_unique([2, 3, 5, 3, 2])) # 5
This works because a ^ a = 0 cancels paired elements, leaving only the unique one.
If you want to practice these patterns interactively, the Python example programs collection covers related exercises. For number-theory problems that combine digit manipulation with bitwise thinking, see the Armstrong number checker. And if array-level operations are your next gap, the sum-of-array walkthrough builds the same iterative-reduction pattern that count_set_bits uses.
Bitwise operators also show up in lower-level contexts: quantised model weights in edge-deployed neural networks use bit-packing to compress 32-bit floats into 4-bit integers, relying on shifts and masks. If the intersection of bit manipulation and AI inference interests you, TinkerLLM lets you experiment with LLM internals at a low entry cost. The count_set_bits pattern from this article is structurally identical to the popcount operations GPUs run during quantised inference.
Primary sources
Frequently asked questions
Can bitwise operators be used with floats in Python?
No. Python raises a TypeError if you apply any bitwise operator to a float. Convert to int first with int() if you need bitwise manipulation on a decimal value.
What is the difference between & (bitwise AND) and 'and' (logical AND)?
The & operator compares each bit of two integers and returns a new integer. The 'and' keyword evaluates two expressions for truthiness and returns one of them (short-circuit). They produce different results: 4 & 5 gives 4, while 4 and 5 gives 5.
Why does ~5 return -6 instead of a positive bit-flip?
Python uses two's complement representation for signed integers. The NOT operator flips every bit, which for any positive integer n yields -(n + 1). So ~5 = -(5 + 1) = -6.
How do left shift and right shift handle negative numbers in Python?
Left shift on a negative number multiplies by 2 per shift position, preserving the sign. Right shift divides by 2 and floors toward negative infinity, so -7 >> 1 gives -4 (not -3). Python's arbitrary-precision integers mean no overflow occurs.
Where do bitwise operators appear in placement coding rounds?
They appear in TCS CodeVita, HackerRank-style online assessments, and Infosys InfyTQ. Common questions: check if a number is a power of 2, swap two numbers without a temp variable, count set bits, and find the single non-repeating element in an array using XOR.
A self-paced playground for building with LLMs.
TinkerLLM is FACE Prep's sister property. A guided environment for shipping real LLM applications, the kind of project that earns a paragraph on your resume, not a line.
Try TinkerLLM (₹299 launch)