Knowledge / Computer Science and Engineering / Bit manipulation

Bit manipulation

Computer Science and Engineering (B.E./B.Tech) · Algorithms · free study notes for exams, placements and interviews

In short

Bit manipulation is the use of the bitwise operators (AND, OR, XOR, NOT, shifts) to read, set and transform the individual binary digits of an integer, treating the integer as a fixed-width array of flags rather than as a quantity. It matters because a single machine instruction does work that would otherwise need a loop or an array: a 32-bit word becomes a set of up to 32 elements, and subset problems become counting from 0 to 2n − 1. It is examined in GATE (through two's complement arithmetic in Digital Logic and through C programming questions), in university Data Structures and Computer Organisation papers, and in almost every placement coding round — Amazon, Microsoft, Google India, Flipkart, Zoho, Goldman Sachs and Morgan Stanley all ask XOR and bitmask questions. On the job it is unavoidable in embedded and systems work (Qualcomm India, Bosch, Texas Instruments India, Tata Elxsi, ISRO), in networking (subnet masks) and in competitive programming.

Explained

Binary representation and two's complement

The operators and the four basic bit operations

OperatorNameRuleTypical use
&AND1 only if both are 1masking, testing, clearing
`\`OR1 if either is 1setting bits, union
^XOR1 if the bits differtoggling, cancelling pairs
~NOTflips every bitbuilding masks
<<left shiftx << k = x × 2kmultiply, build 1<<i
>>right shiftarithmetic (sign-filling) for signed typesdivide by 2k, extract fields
>>>unsigned right shift (Java only)fills with 0treating an int as unsigned

XOR: the properties that generate the question family

Counting and locating bits

Bitmasks: sets, subsets and bitmask DP

Language-specific behaviour and pitfalls

IssueC/C++JavaPython
Integer widthfixed, 32/64-bit, overflow UB for signedfixed 32/64-bit, wraps silentlyarbitrary precision
Right shift of a negativearithmetic; guaranteed two's complement from C++20>> arithmetic, >>> logical>> arithmetic (floors)
Shift count ≥ widthundefined behaviourtaken modulo 32 / 64allowed, gives 0 (or −1)
~xbitwise NOT of fixed widthsame~x = -x - 1, conceptually infinite sign bits
Simulating 32-bitnativenativemask with & 0xFFFFFFFF, then subtract 232 if bit 31 set
Popcount__builtin_popcount / std::popcountInteger.bitCountx.bit_count() (3.10+)

Advantages, limits and complexity

Key points

Formulas and examples

−x = ~x + 1 (two's complement); x < 0 ⟺ ((x >> (w−1)) & 1) = 1, w = word width in bits
Test: (x >> i) & 1 · Set: x | (1 << i) · Clear: x & ~(1 << i) · Toggle: x ^ (1 << i)
Low k bits: x & ((1 << k) − 1) · Field of width w at position p: (x >> p) & ((1 << w) − 1)
x << k = x · 2k (if no overflow); x >> k = ⌊x / 2k⌋ (arithmetic shift, floors)
x & (x − 1) = x with its lowest set bit cleared; x & (−x) = value of the lowest set bit
Power of two: (x > 0) AND ((x & (x − 1)) == 0)
Gray(n) = n ^ (n >> 1); inverse: x = g; for (s = 16; s; s >>= 1) x ^= x >> s
Hamming distance d(x, y) = popcount(x ^ y) bits
XOR of 1…n = n if n mod 4 = 0; 1 if 1; n + 1 if 2; 0 if 3
Number of subsets of an n-set = 2n; number of (mask, submask) pairs = 3n
Bitmask TSP: dp[mask][i] = min over j in mask of dp[mask ^ (1<<i)][j] + cost[j][i]; O(2n · n²) time, O(2n · n) space

Example 1 — bit surgery and two's complement. Let x = 183 = 1011 0111.

Example 2 — popcount by Brian Kernighan, and Hamming distance. x = 156 = 1001 1100.

Stepx (binary)x − 1x & (x−1)count
110011100 (156)10011011 (155)10011000 (152)1
210011000 (152)10010111 (151)10010000 (144)2
310010000 (144)10001111 (143)10000000 (128)3
410000000 (128)01111111 (127)00000000 (0)4

Example 3 — the two single numbers. Array [2, 4, 7, 9, 2, 4]; every value appears twice except 7 and 9.

  1. XOR all: 24 = 6; 67 = 1; 19 = 8; 82 = 10; 104 = 14. So d = 14 = 1110 = 7 ^ 9. ✔
  2. Lowest set bit: 14 & -14 = 2 (bit 1).
  3. Partition on bit 1 — set: {2 (0010), 7 (0111), 2}; clear: {4 (0100), 9 (1001), 4}.
  4. XOR each group: 272 = 7; 494 = 9. Answer {7, 9}, in O(n) time and O(1) space.
  5. Cross-check with the period-4 rule: XOR of 1…10, with 10 mod 4 = 2, should be 11. Longhand: 12 = 3, 3 = 0, 4 = 4, 5 = 1, 6 = 7, 7 = 0, 8 = 8, 9 = 1, 10 = 11. ✔

Example 4 — subset enumeration with a mask. Set {5, 9, 12}, n = 3, so 23 = 8 masks.

maskbitssubsetsum
0000{ }0
1001{5}5
2010{9}9
3011{5, 9}14
4100{12}12
5101{5, 12}17
6110{9, 12}21
7111{5, 9, 12}26

Example 5 — why bitmask DP is worth the ugliness (TSP, n cities).

nBrute force (n−1)!Bitmask DP 2n · n²States 2n · n
10362,880102,40010,240
1587,178,291,2007,372,800491,520
201.22 × 1017419,430,40020,971,520
// idiom sheet
bool isPow2(unsigned x) { return x && !(x & (x - 1)); }
int lowbit(int x)       { return x & -x; }
int popcnt(int x)       { int c = 0; while (x) { x &= x - 1; ++c; } return c; }
int gray(int n)         { return n ^ (n >> 1); }
// all submasks of m, including 0
for (int s = m; ; s = (s - 1) & m) { use(s); if (!s) break; }

Where it is used

Interview questions

Common mistakes

Related topics

Number theory for programmers · Dynamic programming · Recursion and backtracking · Time and space complexity · DSA interview patterns · Searching and binary search

Open in the Knowledge reader →Find jobs →