Skip to content

Expert: advanced patterns and interviews · Tries, union-find and bit manipulation · topic 50 of 61 · 35 min

Bits: AND, OR, XOR and shifts

Explanation

Every integer is stored as bits, 0s and 1s. Bitwise operators work on those bits directly: & (AND), | (OR), ^ (XOR), ~ (NOT), << and >> (shifts). With them you can check, set, clear or toggle one bit, test for a power of two with n & (n − 1), and count set bits. Python integers have no fixed size, so negative numbers and ~ behave differently from 32-bit languages such as Java, C++ and JavaScript.

Numbers are bits underneath

Computers store integers in binary, base 2. Each position is a bit, and bit i is worth 2 to the power i. Bit 0 is the rightmost one. So 13 is 8 + 4 + 1, which is 1101 in binary. In Python, bin(13) gives '0b1101', int("1101", 2) gives 13, and f"{13:08b}" gives '00001101', padded to 8 digits.

The operators

OperatorNameRule for each bitExample
a & bAND1 only if both bits are 112 & 10 = 8 (1100 & 1010 = 1000)
a | bOR1 if at least one bit is 112 | 10 = 14 (1110)
a ^ bXOR1 if the bits are different12 ^ 10 = 6 (0110)
~aNOTflip every bit~12 = −13 in Python
a << kleft shiftmove bits k places left (× 2ᵏ)3 << 2 = 12
a >> kright shiftmove bits k places right (÷ 2ᵏ, rounded down)13 >> 1 = 6

Check, set, clear and toggle one bit

A mask is a number with 1s only in the positions you care about. 1 << i is a mask with only bit i set. Combine it with the right operator:

python
n = 0b1010                     # 10
print((n >> 1) & 1)            # check bit 1   Output: 1
print(n | (1 << 0))            # set bit 0     Output: 11
print(n & ~(1 << 3))           # clear bit 3   Output: 2
print(n ^ (1 << 2))            # toggle bit 2  Output: 14
OR with a mask turns a bit on, AND with the inverted mask turns it off, XOR flips it.

The n & (n − 1) trick

Subtracting 1 from n flips its lowest 1 bit to 0 and turns all the 0s below it into 1s. AND-ing with n then removes exactly that lowest 1 bit. For 12 = 1100, 11 = 1011, and 12 & 11 = 1000 = 8.

A power of two (1, 2, 4, 8…) has exactly one 1 bit, so removing it leaves 0. The test is n > 0 and n & (n − 1) == 0; the n > 0 part rules out 0 and negative numbers. A related trick, n & −n, keeps ONLY the lowest 1 bit: 12 & −12 is 4.

Counting set bits

The number of 1 bits is called the popcount (population count). Three ways in Python: bin(n).count("1"); n.bit_count(), available since Python 3.10; or Brian Kernighan's method, which repeats n &= n − 1 until n is 0 and counts the steps. Kernighan's loop runs once per 1 bit, not once per bit, which interviewers like.

python
def count_bits(n):
    count = 0
    while n:
        n &= n - 1
        count += 1
    return count

print(count_bits(13), bin(13).count("1"), (13).bit_count())   # Output: 3 3 3
Write (13).bit_count() with brackets: 13.bit_count() is a syntax error.

Warning: Python integers are unbounded

In Java, C++ and similar languages, an int has a fixed width such as 32 bits, and negative numbers use two's complement. Python integers grow as large as needed. They behave as if a negative number had infinitely many 1 bits on the left. This changes several things you may have learnt elsewhere.

python
print(~5)                    # Output: -6   (~x is always -x - 1)
print(bin(-5))               # Output: -0b101   (a sign, not two's complement)
print(-1 >> 1)               # Output: -1   (shifting a negative never reaches 0)
print(-5 & 0xFFFFFFFF)       # Output: 4294967291   (the 32-bit pattern of -5)
A loop like while n: n >>= 1 never ends for a negative n. Mask with & 0xFFFFFFFF to imitate 32 bits.

JavaScript goes the other way: its bitwise operators first convert numbers to 32-bit signed integers. So (2 ** 31) | 0 is −2147483648, and >>> is an extra "unsigned" right shift that fills with 0s: −1 >>> 0 is 4294967295.

Real use: permission flags

Many systems pack several yes/no settings into one number. Linux file permissions are the famous example: read = 4 (100), write = 2 (010), execute = 1 (001). chmod 7 means 111, all three; 6 is 110, read and write; 5 is 101, read and execute. chmod 754 gives the owner 7 (rwx), the group 5 (r-x) and everyone else 4 (r--). To test "can write?", check perms & 2 != 0. Feature flags in apps and settings in games are often stored the same way.

Common mistakes

  • Writing 2 ^ 3 for "two to the power three". In Python and JavaScript, ^ is XOR, so 2 ^ 3 is 1. Fix: 2 ** 3, or 1 << 3.
  • Forgetting brackets in JavaScript, Java or C: there, n & 1 == 0 means n & (1 == 0). Python happens to group it as (n & 1) == 0, but brackets make every language safe.
  • Testing a power of two without n > 0, so 0 passes. Fix: n > 0 and n & (n − 1) == 0.
  • Expecting ~x or bin(x) to show 32-bit patterns in Python. Fix: mask with & 0xFFFFFFFF.
  • Off by one with bit positions: the rightmost bit is bit 0, not bit 1.

Need help?

Stuck on a word or an idea? Search this course, or every course, and jump straight to the explanation or a worked question.

Try:

Watch the lesson

Bits: AND, OR, XOR and shifts · 1/8

Bits

This lesson is about bits: the zeros and ones inside every integer, and the operators that work on them directly.

Prefer a video by a teacher? Find free videos on “bit manipulation basics and or xor shift tricks interview python” on YouTube ↗

In real life: Permission flags in an app

A document-sharing app can store what each user may do as one small number instead of several true/false columns: view = 4, comment = 2, edit = 1, just like Linux file permissions. Giving a permission is an OR, taking it away is an AND with the inverted mask, and checking it is an AND. One number per user is quick to store and compare.

python
VIEW, COMMENT, EDIT = 4, 2, 1

perms = VIEW | COMMENT          # 6 = 110
print(perms, bool(perms & EDIT))
perms |= EDIT                   # give edit: 7 = 111
print(perms, f"{perms:03b}")
perms &= ~COMMENT               # take away comment: 5 = 101
print(perms, bool(perms & COMMENT))
Shows 6 False, then 7 111, then 5 False.

Practice (0/4 done)

Task 1 · Code · Python

Write is_power_of_two(n) that returns True if n is a power of two (1, 2, 4, 8, …) and False otherwise. 0 and negative numbers are never powers of two. Use the n & (n − 1) trick, no loops. Example: is_power_of_two(16) returns True and is_power_of_two(6) returns False.

Task 2 · Code · Python

Write count_bits(n) that returns the number of 1 bits in the binary form of n (n ≥ 0). Use Brian Kernighan's method: repeat n &= n − 1 and count the steps. Python integers can be very large, and your function must work for them too. Example: count_bits(13) returns 3, because 13 is 1101.

Task 3 · Code · Python

Write four functions for n ≥ 0 and bit position i ≥ 0 (bit 0 is the rightmost): get_bit(n, i) returns 1 if bit i of n is set, else 0; set_bit(n, i) returns n with bit i set to 1; clear_bit(n, i) returns n with bit i set to 0; toggle_bit(n, i) returns n with bit i flipped. Use shifts and masks. Example: 10 is 1010, so get_bit(10, 1) is 1 and set_bit(10, 0) is 11.

Task 4 · Code · Javascript

Write countSetBits(n) in JavaScript for a whole number n with 0 ≤ n ≤ 4294967295 (any 32-bit unsigned value). Return how many 1 bits it has. JavaScript bitwise operators work on 32-bit SIGNED integers, so for values of 2³¹ and above use >>> (unsigned right shift), not >>: with >>, the number turns negative and a loop like while (n !== 0) may never end. Example: countSetBits(11) returns 3.

Quick quiz

Question 1

1.What is 12 & 10?

Question 2

2.What is 13 ^ 6?

Question 3

3.What does n & (n − 1) do?

Question 4

4.What does ~5 give in Python?

Question 5

5.A file has permission 6 for its owner. What may the owner do?

Question 6

6.Why does "while n: n >>= 1" never end for n = −1 in Python?

Read more (free)

Open a question to see the answer and why. The first ones are this topic's own quiz, so try the quiz above before you peek.

What is 12 & 10?

Answer: 8

1100 AND 1010 keeps only the bits set in both: 1000 = 8.

What is 13 ^ 6?

Answer: 11

1101 XOR 0110 = 1011 = 11: bits that differ become 1.

What does n & (n − 1) do?

Answer: Removes the lowest 1 bit of n

n − 1 flips the lowest 1 bit and the 0s below it, so the AND clears that bit.

What does ~5 give in Python?

Answer: -6

For Python ints, ~x is always −x − 1.

A file has permission 6 for its owner. What may the owner do?

Answer: Read and write

6 = 110: read (4) and write (2), no execute (1).

Why does "while n: n >>= 1" never end for n = −1 in Python?

Answer: -1 >> 1 is still -1

Right-shifting a negative Python int rounds down, so −1 stays −1 forever.

Why use unsigned types for bit manipulation?Related

Answer: Shifts and overflow are well defined for unsigned types

Signed shifts have implementation-defined or undefined cases.

From Bitwise operators

Which expression clears bit 5 of x?Related

Answer: x &= ~(1u << 5)

AND with a mask that has a 0 only at bit 5.

From Masks and flags

Why might XOR be preferred over the sum formula for "missing number" in Java or C++?Related

Answer: A big sum can overflow a fixed-size int; XOR cannot

n(n + 1)/2 can exceed 32 bits; XOR results never grow beyond the inputs' width.

From Bit tricks in interviews

How many bits are in one octet?Related

Answer: 8

An octet is 8 bits. An IPv4 address has 4 octets, so 32 bits.

From Binary and decimal for networking

Pass the quiz (60% or more) or mark this topic as done when you are ready.

Your progress is saved on this device only.

Next steps

  1. 1 more topic in “Tries, union-find and bit manipulation” before its exam: Bit tricks in interviews.
  2. Module 10 exam: Tries, union-find and bits · 14 questions · 25 min, without help. 5 topics of this module still to finish first.
  3. Then the next module, Dynamic programming. 61 topics left in the course before the final exam.

← Previous: Minimum spanning trees