Counting Bits

Strip the Lowest Set Bit with n & (n-1) to Count Set Bits in O(popcount) Time

Counting Bits

Brian Kernighan's trick repeatedly clears the lowest set bit of n with n &= n-1, running in time proportional to the number of set bits (popcount) rather than the bit width — and a DP variant fills a full table in O(n).

4 min read Level 2/5 #dsa#bits#popcount
What you'll learn
  • Implement Brian Kernighan's algorithm to count set bits
  • Explain why the loop runs exactly popcount(n) iterations
  • Build an O(n) popcount table using the recurrence `popcount[i] = popcount[i >> 1] + (i & 1)`

The Hamming weight (or popcount) of an integer is the number of 1-bits in its binary representation. It appears in checksums, compression, error correction, and bitmask DP. JavaScript has no built-in popcount, but two approaches cover all practical needs.

Brian Kernighan’s Algorithm

The expression n & (n - 1) clears the lowest set bit of n. Repeat until n is zero and count the iterations.

function popcount(n) {
  n = n | 0;   // coerce to int32 — safe for values up to 2^31 - 1
  let count = 0;
  while (n !== 0) {
    n &= n - 1; // clear the lowest set bit
    count++;
  }
  return count;
}

console.log(popcount(0b10110100)); // 4  (bits 2,4,5,7 are set)
console.log(popcount(255));        // 8
console.log(popcount(0));          // 0

Why it works: subtracting 1 from n flips the lowest set bit to 0 and sets all lower bits to 1. ANDing with the original n clears those lower bits, leaving everything above the lowest set bit unchanged. Each iteration removes exactly one set bit, so the loop runs exactly popcount(n) times.

n (binary)n - 1 (binary)n & (n-1)Bits removed
1011 01001011 00111011 0000bit 2
1011 00001010 11111010 0000bit 4
1010 00001001 11111000 0000bit 5
1000 00000111 11110000 0000bit 7

O(n) Table with DP

When you need popcount for every integer from 0 to n, build the table in one pass using a simple recurrence: every integer i has the same set bits as i >> 1, plus 1 if i is odd.

function buildPopcountTable(n) {
  const pc = new Int32Array(n + 1);
  for (let i = 1; i <= n; i++) {
    pc[i] = pc[i >> 1] + (i & 1);
  }
  return pc;
}

const pc = buildPopcountTable(8);
console.log([...pc]); // [0,1,1,2,1,2,2,3,1]

This runs in O(n) time and O(n) space. Each entry is computed from an already- computed entry (i >> 1 < i), so no lookup is ever missing.

Checking Power of Two

Kernighan’s trick also gives a one-liner for power-of-two detection: a power of two has exactly one set bit, so n & (n - 1) equals zero for positive powers of two.

const isPow2 = n => n > 0 && (n & (n - 1)) === 0;
console.log(isPow2(1024)); // true
console.log(isPow2(1000)); // false

Up Next

When integers exceed 32 bits — or even 53 bits — you need BigInt. Learn when to switch and how to use BigInt for modular arithmetic.

BigInt Tricks for Large Integers →