- What bitwise operators are โ understanding binary operations at the bit level
- Bitwise AND (&) โ how to find common bits between two numbers
- Bitwise OR (|) โ how to combine bits from two numbers
- Bitwise XOR (^) โ how to find bits that differ between two numbers
- Bitwise NOT (~) โ how to flip all bits (inversion)
- Left Shift (<<) โ how to multiply by powers of 2 efficiently
- Right Shift (>>) โ how to divide by powers of 2 efficiently
- Real-world applications โ permissions, encryption, and more
- Common mistakes โ and how to avoid them
What are Bitwise Operators?
Bitwise operators work on the binary representation of numbers โ they operate on individual bits (0s and 1s). While you might not use them every day, they are incredibly powerful for certain tasks and are widely used in systems programming, encryption, graphics, and performance-critical applications.
๐ก Why learn bitwise operators? They're like a secret weapon in your programming toolkit. They make certain operations 10x faster than regular arithmetic, they're the foundation of many algorithms, and they help you understand how computers actually work at the lowest level.
Before we dive in, let's quickly review how binary numbers work. In our everyday lives, we use the decimal system (base 10) with digits 0-9. Computers use the binary system (base 2) with only two digits: 0 and 1. Here are some examples:
Binary Basics: Decimal 0 = Binary 0000 Decimal 1 = Binary 0001 Decimal 2 = Binary 0010 Decimal 3 = Binary 0011 Decimal 4 = Binary 0100 Decimal 5 = Binary 0101 Decimal 6 = Binary 0110 Decimal 7 = Binary 0111 Decimal 8 = Binary 1000
Now that we understand binary, let's explore each bitwise operator in detail.
1. Bitwise AND (&) โ The "Strict" Operator
The bitwise AND operator (&) compares each bit of two numbers and returns 1 only when both bits are 1. If either bit is 0, the result is 0.
Think of it like a strict parent who only gives permission when everyone agrees. If even one person says "no," the answer is "no."
# Bitwise AND (&) a = 5 # binary: 0101 b = 3 # binary: 0011 result = a & b print(result) # Output: 1 # Let's break it down step by step: # 0101 (5) # & 0011 (3) # ---- # 0001 (1) # Here's what happens at each bit position: # Bit 4: 0 & 0 = 0 # Bit 3: 1 & 0 = 0 # Bit 2: 0 & 1 = 0 # Bit 1: 1 & 1 = 1 โ ONLY this bit is 1 in both numbers! # More examples: print(7 & 3) # 0111 & 0011 = 0011 (3) print(8 & 4) # 1000 & 0100 = 0000 (0) print(15 & 3) # 1111 & 0011 = 0011 (3)
Truth Table for AND
The truth table shows all possible combinations and their results:
| Bit 1 | Bit 2 | Result | Explanation |
|---|---|---|---|
| 1 | 1 | 1 | Both are 1 โ result is 1 โ |
| 1 | 0 | 0 | One is 0 โ result is 0 โ |
| 0 | 1 | 0 | One is 0 โ result is 0 โ |
| 0 | 0 | 0 | Both are 0 โ result is 0 โ |
๐ก Real-World Use: Permission Checking
In operating systems, permissions are often stored as bits. Each bit represents a specific permission, and the AND operator helps check if a user has a particular permission.
# Permission System
READ = 1 # binary: 0001
WRITE = 2 # binary: 0010
EXECUTE = 4 # binary: 0100
user_permission = 5 # User has READ + EXECUTE (0101)
# Check if user has READ permission
if user_permission & READ:
print("โ
User can read files")
else:
print("โ User cannot read files")
# Check if user has WRITE permission
if user_permission & WRITE:
print("โ
User can write files")
else:
print("โ User cannot write files")
# Check if user has EXECUTE permission
if user_permission & EXECUTE:
print("โ
User can execute files")
else:
print("โ User cannot execute files")
# Output:
# โ
User can read files
# โ User cannot write files
# โ
User can execute files
Why this works: The AND operator isolates the specific bit we're checking. If that bit is 1 in the user's permission, the result is non-zero (True). If it's 0, the result is 0 (False).
2. Bitwise OR (|) โ The "Inclusive" Operator
The bitwise OR operator (|) compares each bit and returns 1 if at least one bit is 1. It only returns 0 when both bits are 0.
Think of it like a friendly teacher who says "yes" if anyone in the class agrees. It's much more permissive than AND!
# Bitwise OR (|) a = 5 # binary: 0101 b = 3 # binary: 0011 result = a | b print(result) # Output: 7 # Step by step: # 0101 (5) # | 0011 (3) # ---- # 0111 (7) # Bit 4: 0 | 0 = 0 # Bit 3: 1 | 0 = 1 โ Since ONE bit is 1, result is 1 # Bit 2: 0 | 1 = 1 โ Since ONE bit is 1, result is 1 # Bit 1: 1 | 1 = 1 โ Both are 1, result is 1 # More examples: print(7 | 3) # 0111 | 0011 = 0111 (7) print(8 | 4) # 1000 | 0100 = 1100 (12) print(15 | 3) # 1111 | 0011 = 1111 (15)
Truth Table for OR
| Bit 1 | Bit 2 | Result | Explanation |
|---|---|---|---|
| 1 | 1 | 1 | Both are 1 โ result is 1 โ |
| 1 | 0 | 1 | At least one is 1 โ result is 1 โ |
| 0 | 1 | 1 | At least one is 1 โ result is 1 โ |
| 0 | 0 | 0 | Both are 0 โ result is 0 โ |
๐ก Real-World Use: Combining Permissions
The OR operator is perfect for combining different permissions together. You can use it to build a user's permission set from individual permissions.
# Building Permissions with OR
READ = 1
WRITE = 2
EXECUTE = 4
# Give user READ and WRITE permissions
user_permission = READ | WRITE # binary: 0011 (3)
print(f"User permission value: {user_permission}")
# Give a super user READ, WRITE, and EXECUTE
super_user = READ | WRITE | EXECUTE # binary: 0111 (7)
print(f"Super user permission: {super_user}")
# Check permissions
print(f"Can read? {bool(user_permission & READ)}")
print(f"Can write? {bool(user_permission & WRITE)}")
print(f"Can execute? {bool(user_permission & EXECUTE)}")
# Output:
# User permission value: 3
# Super user permission: 7
# Can read? True
# Can write? True
# Can execute? False
3. Bitwise XOR (^) โ The "Difference" Operator
The bitwise XOR (exclusive OR) operator (^) returns 1 when the bits are different (one is 0 and the other is 1), and 0 when they are the same (both 0 or both 1).
Think of it like a debate judge who only agrees when opinions differ. If both sides agree (both 0 or both 1), the judge says "no." If they disagree (one 0, one 1), the judge says "yes."
# Bitwise XOR (^) a = 5 # binary: 0101 b = 3 # binary: 0011 result = a ^ b print(result) # Output: 6 # Step by step: # 0101 (5) # ^ 0011 (3) # ---- # 0110 (6) # Bit 4: 0 ^ 0 = 0 (same โ 0) # Bit 3: 1 ^ 0 = 1 (different โ 1) # Bit 2: 0 ^ 1 = 1 (different โ 1) # Bit 1: 1 ^ 1 = 0 (same โ 0) # More examples: print(7 ^ 3) # 0111 ^ 0011 = 0100 (4) print(8 ^ 4) # 1000 ^ 0100 = 1100 (12) print(15 ^ 3) # 1111 ^ 0011 = 1100 (12)
Truth Table for XOR
| Bit 1 | Bit 2 | Result | Explanation |
|---|---|---|---|
| 1 | 1 | 0 | Same โ 0 โ |
| 1 | 0 | 1 | Different โ 1 โ |
| 0 | 1 | 1 | Different โ 1 โ |
| 0 | 0 | 0 | Same โ 0 โ |
๐ก Real-World Use: Simple Encryption
XOR has a special property: it's reversible. If you XOR a number with a key, you can get the original number back by XORing with the same key again. This makes it perfect for simple encryption!
# Simple XOR Encryption (reversible!)
message = 42
key = 7
print(f"Original message: {message}")
# Encrypt
encrypted = message ^ key
print(f"Encrypted: {encrypted}")
# Decrypt (XOR again with the same key)
decrypted = encrypted ^ key
print(f"Decrypted: {decrypted}")
# Output:
# Original message: 42
# Encrypted: 45
# Decrypted: 42
4. Bitwise NOT (~) โ The "Inverter"
The bitwise NOT operator (~) flips all the bits: 0 becomes 1 and 1 becomes 0. In Python, it's written as ~ and returns the negative value plus 1.
Think of it like a light switch that toggles the current state. If the light is on (1), it turns off (0). If it's off (0), it turns on (1).
# Bitwise NOT (~) a = 5 # binary: 0101 result = ~a print(result) # Output: -6 # Why -6? Python uses two's complement! # 5 in binary: 0000 0101 # ~5 in binary: 1111 1010 (which is -6 in two's complement) # More examples: print(~7) # Output: -8 print(~3) # Output: -4 print(~10) # Output: -11
๐ Understanding Two's Complement: Python uses two's complement to represent negative numbers. In this system, ~a is equivalent to -(a + 1). So ~5 = -(5 + 1) = -6. This is why ~5 doesn't give you 2 (the simple bitwise inversion of 0101 is 1010, which is 10, not -6).
5. Left Shift (<<) โ The "Multiply by 2" Operator
The left shift operator (<<) moves all bits to the left by a specified number of positions. Each shift to the left doubles the number (multiplies by 2).
Think of it like moving decimal points in a number, but in binary. Just like adding a zero to the right of a decimal number multiplies it by 10, shifting bits left multiplies by 2.
# Left Shift (<<) a = 5 # binary: 0101 result = a << 1 print(result) # Output: 10 # How it works: # 5 in binary: 0101 # << 1: 1010 (which is 10) # It's like adding a zero at the end: 0101 โ 1010 result = a << 2 print(result) # Output: 20 # a << n is the same as: a * (2 ** n) print(5 << 1) # 5 * 2 = 10 print(5 << 2) # 5 * 4 = 20 print(5 << 3) # 5 * 8 = 40 # More examples: print(7 << 1) # 7 * 2 = 14 print(3 << 3) # 3 * 8 = 24 print(10 << 2) # 10 * 4 = 40
๐ก Real-World Use: Fast Multiplication
Left shift is much faster than regular multiplication because it's a single CPU instruction. It's used in performance-critical applications where speed matters.
# Fast Multiplication by Powers of 2
value = 25
# Multiply by 2
fast_multiply_2 = value << 1
print(f"25 ร 2 = {fast_multiply_2}") # Output: 50
# Multiply by 4 (2^2)
fast_multiply_4 = value << 2
print(f"25 ร 4 = {fast_multiply_4}") # Output: 100
# Multiply by 8 (2^3)
fast_multiply_8 = value << 3
print(f"25 ร 8 = {fast_multiply_8}") # Output: 200
# Multiply by 16 (2^4)
fast_multiply_16 = value << 4
print(f"25 ร 16 = {fast_multiply_16}") # Output: 400
6. Right Shift (>>) โ The "Divide by 2" Operator
The right shift operator (>>) moves all bits to the right by a specified number of positions. Each shift to the right halves the number (divides by 2, rounding down).
Think of it like removing the last digit from a number. Just like removing the last digit from a decimal number divides it by 10, shifting bits right divides by 2.
# Right Shift (>>) a = 20 # binary: 10100 result = a >> 1 print(result) # Output: 10 # How it works: # 20 in binary: 10100 # >> 1: 01010 (which is 10) # It's like removing the last bit: 10100 โ 01010 result = a >> 2 print(result) # Output: 5 # a >> n is the same as: a // (2 ** n) print(20 >> 1) # 20 // 2 = 10 print(20 >> 2) # 20 // 4 = 5 print(20 >> 3) # 20 // 8 = 2 # More examples: print(15 >> 1) # 15 // 2 = 7 print(8 >> 2) # 8 // 4 = 2 print(100 >> 3) # 100 // 8 = 12
๐ก Real-World Use: Fast Division
Right shift is much faster than regular division by powers of 2. It's used in game development, graphics, and systems programming.
# Fast Division by Powers of 2
value = 100
# Divide by 2
fast_divide_2 = value >> 1
print(f"100 รท 2 = {fast_divide_2}") # Output: 50
# Divide by 4 (2^2)
fast_divide_4 = value >> 2
print(f"100 รท 4 = {fast_divide_4}") # Output: 25
# Divide by 8 (2^3)
fast_divide_8 = value >> 3
print(f"100 รท 8 = {fast_divide_8}") # Output: 12
# Divide by 16 (2^4)
fast_divide_16 = value >> 4
print(f"100 รท 16 = {fast_divide_16}") # Output: 6
7. Quick Reference Table
Here's a complete reference of all bitwise operators:
| Operator | Example | Result | Description | Real-World Use |
|---|---|---|---|---|
& |
5 & 3 |
1 |
AND (both bits must be 1) | Permission checking |
| |
5 | 3 |
7 |
OR (at least one bit is 1) | Combining permissions |
^ |
5 ^ 3 |
6 |
XOR (bits are different) | Simple encryption |
~ |
~5 |
-6 |
NOT (flips all bits) | Bitwise inversion |
<< |
5 << 1 |
10 |
Left shift (multiply by 2) | Fast multiplication |
>> |
20 >> 1 |
10 |
Right shift (divide by 2) | Fast division |
8. Real-World Applications
Bitwise operators are used in many real-world applications:
๐ Cryptography
XOR is fundamental to many encryption algorithms
๐ฎ Game Development
Fast multiplication/division for graphics and physics
๐ File Compression
Bit manipulation for efficient data storage
๐ Network Protocols
IP addresses, ports, and packet headers
๐พ Operating Systems
Permissions, flags, and system calls
๐ผ๏ธ Image Processing
Pixel manipulation and color operations
9. Common Mistakes to Avoid
โ Mistake 1: Confusing & with and
& is a bitwise operator, and is a logical operator. They are NOT interchangeable!
# WRONG (using bitwise & for logical condition)
if x > 0 & x < 10: # This is bitwise AND, not logical AND!
print("x is between 0 and 10")
# CORRECT (use 'and' for logical conditions)
if x > 0 and x < 10:
print("x is between 0 and 10")
โ Mistake 2: Misunderstanding ~ (NOT)
~a returns -(a + 1), not the simple bitwise inverse you might expect.
# What beginners often expect x = 5 print(~x) # Output: -6 (not 2!) # If you want bitwise NOT for 8-bit numbers print(~x & 0xFF) # Output: 250 (the bitwise inverse in 8 bits)
โ Mistake 3: Confusing | with or
| is bitwise OR, or is logical OR. They're different!
# WRONG (using bitwise OR for logical OR)
if x > 0 | x < 10: # This is bitwise OR!
print("Condition met")
# CORRECT (use 'or' for logical OR)
if x > 0 or x < 10:
print("Condition met")
Try It Yourself!
Experiment with bitwise operators directly in your browser. Modify the code and see the results in real time.
BITWISE OPERATORS
========================================
Using: a = 5 (binary: 0b101), b = 3 (binary: 0b11)
1. BITWISE AND (&)
5 & 3 = 1 (binary: 0b1)
โ Only 1 when BOTH bits are 1
2. BITWISE OR (|)
5 | 3 = 7 (binary: 0b111)
โ 1 when AT LEAST ONE bit is 1
3. BITWISE XOR (^)
5 ^ 3 = 6 (binary: 0b110)
โ 1 when bits are DIFFERENT
4. BITWISE NOT (~)
~5 = -6
~3 = -4
โ Flips all bits
5. LEFT SHIFT (<<)
5 << 1 = 10 (Multiply by 2)
5 << 2 = 20 (Multiply by 4)
6. RIGHT SHIFT (>>)
5 >> 1 = 2 (Divide by 2)
5 >> 2 = 1 (Divide by 4)
7. REAL-WORLD: Permission System
User Permission (READ + WRITE): 3
Can read? True
Can write? True
Can execute? False
โ Bitwise operators are powerful for low-level operations!
๐ You've Mastered Python Bitwise Operators!
You understand all bitwise operators (&, |, ^, ~, <<, >>) and their real-world applications. These are essential for systems programming!
Quick Quiz โ Test Your Knowledge
5 & 3?5 | 3 return?5 ^ 3?~5 return in Python?5 << 1 do?Frequently Asked Questions
๐ค What's the difference between & and and?
& is a bitwise operator that compares each bit of two numbers. and is a logical operator that works with boolean values (True and False). They are not interchangeable. Use & for bit manipulation and and for logical conditions like if x > 0 and x < 10.
๐ง When should I use bitwise operators?
๐ Why does ~5 equal -6?
~a is equivalent to -(a + 1). So ~5 = -(5 + 1) = -6. This is because flipping all bits of 5 (0000 0101) gives 1111 1010, which in two's complement is -6.
โก Are bitwise operators faster than arithmetic?
x << 1 is much faster than x * 2. However, the performance difference is only noticeable in tight loops or performance-critical code. For everyday programming, readability matters more than micro-optimizations.
๐ What's the difference between | and or?
| is a bitwise OR operator that works on bits (numbers). It combines the bits of two numbers. or is a logical operator that works with boolean values. They are not interchangeable. Use | for bit manipulation and or for logical conditions like if x > 0 or y > 0.
๐ฏ How do I check if a specific bit is set in a number?
n (0-indexed from the right) is set, use: if number & (1 << n):. For example, if x & (1 << 3): checks if bit 3 (the 4th bit from the right) is set in x. This is commonly used in permission systems and flag checking.
๐ Where to Go From Here
Now that you understand Python bitwise operators, here are some related topics to explore:
โญ Special Operators
Learn about identity and membership operators
๐ฏ Decision Making
Use conditions to control program flow
๐ File Handling
Learn about file operations in Python