Topics › Bit Manipulation › Learn Bit Manipulation

Check if the i-th bit is Set or Not

Easy TUF ID 177 A2Z

Problem

You are given an integer n and a position i. Return true if the i-th bit of n is 1 (set) and false if it is 0 (unset). Bits are counted from the right starting at 0, so bit 0 is the least significant bit with weight 1, bit 1 has weight 2, and bit i has weight 2^i.

Constraints: 0 ≤ i ≤ 31; n is any 32-bit signed integer, but the problem is usually asked for n ≥ 0. For a negative n the answer refers to its two’s-complement pattern, so bit 31 of any negative number is set.

Example 1

n = 13, i = 2
answer = true        // 13 = 1101, bit 2 (weight 4) is 1

Example 2

n = 13, i = 1
answer = false       // 13 = 1101, bit 1 (weight 2) is 0

Example 3

n = 0, i = 0
answer = false       // zero has no set bits at all

Approach 1: Brute force, peel off digits by division

Intuition. Dividing by 2 drops the lowest binary digit, the same way dividing by 10 drops the lowest decimal digit. Divide i times and the bit we care about is now the lowest one, where % 2 reads it. This is the method you would use with no knowledge of bitwise operators at all.

Algorithm.

  1. Take n as an unsigned 32-bit value by masking it into a long (so a negative n is treated as its bit pattern rather than as a negative quotient).
  2. Divide by 2, i times.
  3. Return whether the remainder modulo 2 is 1.
static boolean bruteForce(int n, int i) {
    long v = n & 0xFFFFFFFFL;              // unsigned view, so a negative n behaves like its 32-bit pattern
    for (int k = 0; k < i; k++) v /= 2;
    return v % 2 == 1;
}

Complexity. Time O(i): one division per position below the one asked about. Space O(1).

The 0xFFFFFFFFL mask is only there for negative inputs. Without it, -1 / 2 in Java is 0 (division truncates toward zero), and the loop would say every high bit of -1 is unset. For n ≥ 0 it changes nothing.

Approach 2: Mask with a left shift

Intuition. 1 << i is a number whose only set bit is at position i. AND-ing n with it zeroes every other position, so the result is either 0 (bit i of n was 0) or 2^i (it was 1). We do not care which non-zero value we get, so we compare against 0.

Algorithm.

  1. Build the mask 1 << i.
  2. Return (n & mask) != 0.
static boolean leftShiftMask(int n, int i) {
    return (n & (1 << i)) != 0;
}

Complexity. Time O(1): one shift, one AND, one comparison. Space O(1).

The comparison must be against 0, not against 1. For i = 2 and n = 13, n & 4 is 4, so == 1 would wrongly report the bit as unset. The one case where == 1 is right is i = 0, which is why the bug often survives a quick test.

Approach 3: Optimal, bring the bit down with a right shift

Intuition. Instead of moving the mask up to the bit, move the bit down to the mask. n >> i shifts the whole number right by i, so the bit that was at position i is now at position 0, and & 1 reads it as exactly 0 or 1. This version is the one to reach for when you want the bit’s value as an integer rather than as a boolean, for example to add it to a counter.

Algorithm.

  1. Compute n >> i.
  2. AND with 1 and compare with 1.
static boolean rightShift(int n, int i) {
    return ((n >> i) & 1) == 1;
}

Dry run on n = 13 = 1101:

i n » i (n » i) & 1 answer
0 1101 1 true
1 110 0 false
2 11 1 true
3 1 1 true
4 0 0 false

Complexity. Time O(1), space O(1).

Both constant-time versions give identical answers for every n and i, including negatives: >> is an arithmetic shift that copies the sign bit into the vacated positions, but the & 1 only looks at position 0, which holds the original bit i regardless of what was shifted in above it.

Beyond checking: set, clear, toggle

The same mask drives the three sibling operations. OR turns a bit on, AND with the inverted mask turns it off, XOR flips it.

static int setBit(int n, int i) {
    return n | (1 << i);
}
static int clearBit(int n, int i) {
    return n & ~(1 << i);
}
static int toggleBit(int n, int i) {
    return n ^ (1 << i);
}

On 13 = 1101: setBit(13, 1) = 1111 = 15, clearBit(13, 2) = 1001 = 9, toggleBit(13, 0) = 1100 = 12. Setting an already-set bit or clearing an already-clear one leaves n unchanged, which makes these safe to call without checking first.

Edge cases and pitfalls