Sum of Two Integers
Add two integers without + or - by folding XOR (sum without carry) with (a & b) << 1 (the carry) until the carry vanishes.
Open on LeetCode ↗Intuition
It is easy to think XOR alone computes addition, but XOR only gives the sum WITHOUT carrying -- 1^1 lands on 0 and silently throws away the carry that a real addition would produce. The fix is to compute the carry separately: a & b marks every position where both bits were 1, and shifting that left by one places the carry where it belongs for the next column, exactly like carrying a digit in grade-school addition. A single pass is not enough, because folding the carry back in can itself produce a new carry, so you loop -- treating the running sum as the new 'a' and the carry as the new 'b' -- until the carry finally reaches zero. In Python, integers are arbitrary precision, so negative numbers do not wrap the way they do in a fixed-width language; you have to explicitly mask to 32 bits at each step and reinterpret the top bit as a sign to get correct two's-complement behavior.
Addition without +: XOR gives the sum ignoring carries, AND-then-shift gives the carries alone. Repeat until no carries remain. In Python the 32-bit masking is manual because integers are unbounded; C++ and Java get the wraparound for free.
Approach
Compute sum without carry via XOR
a ^ b adds each bit position independently and ignores any carry out of that position -- it is correct wherever the two bits differ, and wrong (drops a 1) wherever both bits are 1.
Compute the carry via (a & b) << 1
a & b identifies every bit position where both operands had a 1, meaning a carry was generated there. Shifting that result left by one moves each carry into the next higher bit position, ready to be added in.
Loop until the carry is zero
Set a to the XOR result and b to the carry, then repeat. Because Python ints do not wrap at 32 bits, mask both to 0xFFFFFFFF on every step, and once the loop ends, reinterpret the top bit as a sign bit to recover the correct negative value if needed.
Solution & live demo
Common pitfalls
Omitting the mask in Python
while b:
carry = (a & b) << 1
a, b = a ^ b, carrycarry = ((a & b) << 1) & MASK a = (a ^ b) & MASK
Python integers never overflow, so a negative operand's infinite sign extension makes the carry grow forever and the loop never terminates. Masking to 32 bits simulates fixed-width hardware.
Returning the masked value directly
return a
return a if a < 0x80000000 else ~(a ^ MASK)
After masking, a negative result is stored as a large positive number in two's-complement form. It has to be converted back to Python's signed representation or every negative answer is reported as a huge positive.
Computing the carry after updating a
a = a ^ b carry = (a & b) << 1
carry = ((a & b) << 1) & MASK a = (a ^ b) & MASK
The carry depends on the original a, so overwriting it first computes the carry from a value that no longer exists. Both must be derived from the same pre-update pair.
Edge cases
The carry (a & b) << 1 is immediately 0, so the loop exits after zero or one iteration with the nonzero operand as the answer.
After masking to 32 bits, the same XOR/carry loop works identically -- the two's-complement bit pattern handles sign automatically.
All intermediate values are masked to 0xFFFFFFFF each iteration to simulate fixed-width overflow the way a real 32-bit adder would.
Reinterpret the masked 32-bit value as negative (two's complement) before returning, since Python would otherwise treat it as a large positive number.