Python tutorials > Core Python Fundamentals > Operators and Expressions > What are bitwise operators?
What are bitwise operators?
Understanding Bitwise Operators in Python
Bitwise operators in Python allow you to manipulate individual bits within integers. They operate on binary representations of numbers, performing logical operations on corresponding bits. This tutorial explores these operators, their functionality, and practical applications.
Introduction to Bitwise Operators
Bitwise operators work directly with the binary representation of integers. Understanding how numbers are represented in binary is crucial for effectively using these operators. Each integer is treated as a sequence of bits (0s and 1s), and the operators perform logical operations on these bits.
The Bitwise AND Operator (&)
The bitwise AND operator (&) compares corresponding bits of two operands. If both bits are 1, the resulting bit is 1; otherwise, the resulting bit is 0. In the example, 5 (0101) AND 3 (0011) results in 1 (0001) because only the rightmost bit is 1 in both numbers.
a = 5 # Binary: 0101
b = 3 # Binary: 0011
result = a & b # Binary: 0001 (Decimal: 1)
print(result)
The Bitwise OR Operator (|)
The bitwise OR operator (|) compares corresponding bits of two operands. If at least one bit is 1, the resulting bit is 1; otherwise, the resulting bit is 0. In the example, 5 (0101) OR 3 (0011) results in 7 (0111) because at least one of the corresponding bits is 1.
a = 5 # Binary: 0101
b = 3 # Binary: 0011
result = a | b # Binary: 0111 (Decimal: 7)
print(result)
The Bitwise XOR Operator (^)
The bitwise XOR (exclusive OR) operator (^) compares corresponding bits of two operands. If the bits are different, the resulting bit is 1; if they are the same, the resulting bit is 0. In the example, 5 (0101) XOR 3 (0011) results in 6 (0110) because the differing bits result in a 1.
a = 5 # Binary: 0101
b = 3 # Binary: 0011
result = a ^ b # Binary: 0110 (Decimal: 6)
print(result)
The Bitwise NOT Operator (~)
The bitwise NOT operator (~) is a unary operator that inverts all the bits of its operand. 0 becomes 1, and 1 becomes 0. Due to the two's complement representation of negative numbers, the result might seem unexpected. In the example, ~5 results in -6 because of how Python (and most languages) represents negative numbers using two's complement. The NOT operator flips all bits, and then the value is interpreted as a negative number in two's complement format.
a = 5 # Binary: 0101
result = ~a # Binary: ...11111111111111111111111111111010 (Decimal: -6)
print(result)
The Left Shift Operator (<<)
The left shift operator (<<) shifts the bits of the left operand to the left by the number of positions specified by the right operand. Zeroes are shifted in from the right. In the example, 5 (0101) << 2 shifts the bits two places to the left, resulting in 20 (010100). Effectively, this multiplies the number by 2 raised to the power of the right operand (5 * 2^2 = 20).
a = 5 # Binary: 0101
result = a << 2 # Binary: 010100 (Decimal: 20)
print(result)
The Right Shift Operator (>>)
The right shift operator (>>) shifts the bits of the left operand to the right by the number of positions specified by the right operand. The rightmost bits are discarded. In most cases, zeroes are shifted in from the left for positive numbers. For negative numbers, the behavior (arithmetic or logical shift) might be platform-dependent. In the example, 5 (0101) >> 2 shifts the bits two places to the right, resulting in 1 (0001). Effectively, this divides the number by 2 raised to the power of the right operand (5 // 2^2 = 1, integer division).
a = 5 # Binary: 0101
result = a >> 2 # Binary: 0001 (Decimal: 1)
print(result)
Real-Life Use Case: Setting and Clearing Flags
Bitwise operators are frequently used for manipulating flags or status bits in embedded systems or low-level programming. Each bit can represent a different attribute or state. This example demonstrates setting, checking, and clearing individual flags using bitwise OR, AND, and NOT operators.
FLAG_READ = 1 # Binary: 0001
FLAG_WRITE = 2 # Binary: 0010
FLAG_EXECUTE = 4 # Binary: 0100
permissions = 0 # Initially no permissions
# Set READ and WRITE permissions
permissions |= FLAG_READ | FLAG_WRITE # Binary: 0011 (Decimal: 3)
# Check if READ permission is set
is_readable = permissions & FLAG_READ != 0 # True
# Clear WRITE permission
permissions &= ~FLAG_WRITE # Binary: 0001 (Decimal: 1)
print(f'Permissions: {permissions}')
print(f'Is Readable: {is_readable}')
When to use them
Use bitwise operators when:
Memory Footprint
Bitwise operators themselves don't directly reduce memory footprint, but using them to represent multiple flags or states within a single integer can significantly reduce the amount of memory required compared to using separate boolean variables for each flag. This is particularly relevant in memory-constrained environments.
Best Practices
Interview Tip
When asked about bitwise operators in an interview, demonstrate your understanding by explaining their functionality, providing examples, and mentioning their common use cases (e.g., flag manipulation, low-level programming). Be prepared to discuss the bitwise NOT operator and its behavior with negative numbers. Also be prepared to discuss efficiency considerations, especially space efficiency.
Pros and Cons
Pros
Cons
FAQ
-
Why does `~5` result in `-6`?
This is due to the two's complement representation of negative numbers. The bitwise NOT operator inverts all the bits of 5 (0101). The resulting binary value is then interpreted as a negative number in two's complement format, which is -6.
-
Are bitwise operators faster than other arithmetic operators?
In general, bitwise operators are very fast because they are directly supported by the hardware. However, the actual performance difference may depend on the specific operation and the hardware architecture. For certain operations, compilers might optimize other arithmetic operations to be equally efficient.
-
Can bitwise operators be used with floating-point numbers?
No, bitwise operators can only be used with integers. They operate on the binary representation of integers, which is fundamentally different from the representation of floating-point numbers.