JS Bitwise (Python Programming)
Learn JS Bitwise (Python Programming) step by step with clear examples and exercises.
Why This Matters
Understanding JavaScript bitwise operations is essential for manipulating individual bits within an integer, which can be useful for tasks such as setting, clearing, and testing specific bits, as well as performing arithmetic operations on integers more efficiently. Although JavaScript doesn't natively support bitwise operators, we can simulate them using Python to gain experience with these concepts. This knowledge is valuable for low-level programming tasks, such as optimizing algorithms, implementing cryptography, and working with hardware.
Prerequisites
To follow this lesson, you should be familiar with the following topics:
- Basic Python syntax
- Variables and data types
- Arithmetic operations
- Control structures (if/else, for loops)
- Understanding binary numbers and their representation
- Familiarity with JavaScript (optional but recommended for a better understanding of the origins of these concepts)
Core Concept
JavaScript bitwise operators can be categorized into three groups: AND (&), OR (|), and XOR (^). Each operator performs a specific operation on the corresponding bits of two integers. In Python, we can use the bitwise operators &, |, and ^ as well as ~ for bitwise NOT.
AND (&)
The AND operator compares each bit in both operands. If both bits are 1, the result is 1; otherwise, the result is 0. In Python:
a = 6 # binary: 110
b = 3 # binary: 011
print(bin(a & b)) # Output: '0b010' (binary for decimal 2)
OR (|)
The OR operator sets the result bit to 1 if either of the corresponding bits in both operands is 1. In Python:
a = 6 # binary: 110
b = 3 # binary: 011
print(bin(a | b)) # Output: '0b111' (binary for decimal 7)
XOR (^)
The XOR operator sets the result bit to 1 if either, but not both, of the corresponding bits in both operands is 1. In Python:
a = 6 # binary: 110
b = 3 # binary: 011
print(bin(a ^ b)) # Output: '0b101' (binary for decimal 5)
Bitwise NOT (~)
The bitwise NOT operator flips all the bits in an integer. In Python:
a = 6 # binary: 110
print(bin(~a)) # Output: '0b-0011010' (binary for decimal -6)
Shift Operators
In addition to the bitwise operators, we have two shift operators in Python: left shift (<<) and right shift (>>). The left shift operator shifts bits to the left by a specified number of positions, filling the vacated positions with zeros. The right shift operator shifts bits to the right by a specified number of positions, filling the vacated positions with the most significant bit (MSB) for signed integers or zeros for unsigned integers.
Left Shift (<<)
The left shift operator moves each bit in an integer one position to the left and fills the vacated rightmost position with a zero. In Python:
a = 4 # binary: 100
print(bin(a << 1)) # Output: '0b1000' (binary for decimal 8)
Right Shift (>>)
The right shift operator moves each bit in an integer one position to the right and fills the vacated leftmost position with the MSB for signed integers or zeros for unsigned integers. For signed integers, the MSB is determined as follows:
- If the number is positive, the MSB is 0.
- If the number is negative, the MSB is 1.
In Python:
a = -5 # binary: 1010 (signed: 1111 0101)
print(bin(a >> 2)) # Output: '0b1' (binary for decimal 1)
Arithmetic Right Shift (>>>)
For unsigned integers, the arithmetic right shift operator behaves the same as the regular right shift operator. However, for signed integers, the arithmetic right shift operator fills the vacated leftmost position with the sign bit (the MSB) instead of zeros when shifting to the right. This ensures that the resulting number has the correct sign.
In Python:
a = -5 # binary: 1010 (signed: 1111 0101)
print(bin(a >> 2)) # Output: '0b1' (binary for decimal 1)
print(bin(-a >>> 2)) # Output: '0b1101' (binary for decimal -13)
Worked Example
Let's write a Python function that uses bitwise operations to find the first set bit (the rightmost non-zero bit) in an integer.
def find_first_set_bit(n):
if n == 0:
return None
for i in range(32):
if (1 << i) & n != 0:
return i
print(find_first_set_bit(13)) # Output: 3
In this example, we use the bitwise left shift operator << to generate powers of 2 and compare them with the input number using the AND operator &. When a power of 2 matches a set bit in the input number, we return its index.
Common Mistakes
- Forgetting to handle the case when the input is zero: If the input is zero, there are no set bits, so we should return None or an appropriate error message.
- Using the wrong operator for a specific task: Be sure to understand which bitwise operation is best suited for your problem.
- Not accounting for negative numbers: When dealing with signed integers, remember that the leftmost bit (bit 0) represents the sign: 0 for positive and 1 for negative numbers.
- Misunderstanding shift operators: Be aware of the differences between regular right shift, arithmetic right shift, and the left shift operator.
- Not checking for overflow or underflow when performing arithmetic operations on large integers: Python has a built-in
math.isclose()function that can help you check if two numbers are close to each other within a specified tolerance.
Common Mistake Example
def find_first_set_bit(n):
if n == 0:
return None
for i in range(32):
if (1 << i) & n != 0:
return i + 1 # Mistake: offsetting the result by 1!
print(find_first_set_bit(-5)) # Output: 32 instead of 1
Practice Questions
- Write a function that takes an integer and returns the number of set bits (1s) it has.
- Given two integers, write a function that checks whether they have at least one common set bit.
- Write a function that swaps the nth and mth bits in an integer.
- Write a function that rotates an integer to the left by k positions.
- Write a function that rotates an integer to the right by k positions.
- Write a function that checks if an integer is a power of 2.
- Write a function that finds the maximum set bit (the leftmost non-zero bit) in an integer.
- Write a function that performs a binary search using bitwise operations.
- Write a function that calculates the sum of two integers using only bitwise operators and without using the addition operator (+).
- Write a function that multiplies two integers using only bitwise operators and without using the multiplication operator (*).
FAQ
What is the difference between AND (&), OR (|), and XOR (^) operators?
The AND operator compares each bit in both operands, setting the result bit to 1 only if both input bits are 1. The OR operator sets the result bit to 1 if either of the corresponding bits in both operands is 1. The XOR operator sets the result bit to 1 if either, but not both, of the corresponding bits in both operands is 1.
What does the bitwise NOT operator do?
The bitwise NOT operator flips all the bits in an integer. For example, applying ~ to the binary number 1010 results in the binary number 0101.
How can I find the first set bit (rightmost non-zero bit) in an integer?
You can write a function that uses a loop and compares each power of 2 with the input number using the AND operator. When a power of 2 matches a set bit in the input number, you return its index. Here's an example:
def find_first_set_bit(n):
if n == 0:
return None
for i in range(32):
if (1 << i) & n != 0:
return i