Coding Interview Patterns Module 17 – Bit manipulation
Divide two integers: shifts, carries and 32 bits
Divide two 32-bit integers without /, * or %, and add two without +, as a chip without those instructions must: the problems and the brute force.
What you will learn
- Compute the quotient of two 32-bit integers with shifts and subtraction, rounded toward zero
- Prove the shift-and-subtract division correct with an invariant
- Handle the signs and the one quotient that overflows, INT_MIN / -1, in five languages
- Add two integers without + using XOR and carries, and show why 32 rounds suffice
- Simulate 32-bit overflow in Python and JavaScript with masks, | 0 and Math.imul
Before you start
What you’ll learn · Before you start
What you will learn
- Compute the quotient of two 32-bit integers with shifts and subtraction, rounded toward zero
- Prove the shift-and-subtract division correct with an invariant
- Handle the signs and the one quotient that overflows, INT_MIN / -1, in five languages
- Add two integers without + using XOR and carries, and show why 32 rounds suffice
- Simulate 32-bit overflow in Python and JavaScript with masks, | 0 and Math.imul
Before you start
On this page
Dividing two integers without the division operator means building the quotient from shifts, subtraction and comparisons, the way long division works on paper, but in base 2: the quotient is a sum of powers of two, so the divisor shifted left by k is subtracted whenever it still fits, for k from 31 down to 0. Adding without + works one level lower: XOR adds bits without carrying, and AND shows where the carries are. Interviews ask both because the ideas are short and the 32-bit edges are not: the one quotient that overflows, Python’s integers that never do, and JavaScript’s doubles. Here are both problems, their brute force with its cost, and what to notice.
Two problems for a chip without a divider
A metering chip has no divide or multiply instruction, and its firmware must do the arithmetic by hand.
Problem A: divide two integers. Given 32-bit signed integers a and b, with b ≠ 0, return a / b rounded toward zero, as C, Java and Go round an integer quotient, using only addition, subtraction, comparisons and bit operations. The quotient −2³¹ / −1 does not fit in 32 bits; return 2³¹ − 1 for it.
- 100 / 7 gives 14, and 7 / −2 gives −3.
- −2147483648 / −1 gives 2147483647, and 0 / 5 gives 0.
Problem B: add two integers. Given 32-bit signed a and b, return their sum with 32-bit wraparound, as a Java
int would hold it, using only bit operations.
- 5 + 9 gives 14, and −3 + 1 gives −2.
- 2147483647 + 1 gives −2147483648.
What the two problems ask for
Text description of the diagram
The upper panel is a number line from −5 to 0 with a point at −3.5, the exact value of 7 / −2. The integer −3 is circled as the quotient rounded toward zero, which C, Java and Go return and which problem A asks for; −4, circled with a dashed line, is the value rounded down, which Python's // operator returns.
The lower panel adds 1 to 2147483647 in 32 bits. 2147483647 is 0111…1111 and 1 is 0000…0001; the carry runs through every bit into bit 31, the sign bit, so the sum is 1000…0000, which a signed 32-bit integer reads as −2147483648. Problem B asks for that wrapping sum.
The brute force, and why it fails at these sizes
Subtract the divisor until it no longer fits, and count the subtractions; add by incrementing one step at a time:
# Both problems by brute force. A: subtract the divisor until it no longer fits, counting the subtractions.
# B: add b to a one step at a time with a bitwise increment, which needs no + at all.
INT_MIN, INT_MAX = -(2**31), 2**31 - 1
def divide_by_subtracting(a, b):
"""Problem A: a / b rounded toward zero, by repeated subtraction, and the subtractions it took."""
if a == INT_MIN and b == -1:
return INT_MAX, 0
negative = (a < 0) != (b < 0)
a, b = abs(a), abs(b)
q = 0
while a >= b:
a -= b
q += 1
return (-q if negative else q), q
def increment(x):
"""x + 1 with bit operations: flip the trailing 1s to 0 and the lowest 0 to 1."""
bit = 1
while x & bit:
x ^= bit
bit <<= 1
return x | bit
def add_by_counting(a, b):
"""Problem B for b >= 0: increment a, b times."""
for _ in range(b):
a = increment(a)
return a
for a, b in ((100, 7), (7, -2), (0, 5), (-2147483648, -1)):
q, steps = divide_by_subtracting(a, b)
print(f"A: {a} / {b} -> {q} ({steps:,} subtractions)")
print(f"A: -2147483648 / 1 would take {2**31:,} subtractions")
print("B: 5 + 9 ->", add_by_counting(5, 9), " (9 increments)")
print(f"B: 1 + 2147483646 would take {2147483646:,} increments") Output
A: 100 / 7 -> 14 (14 subtractions) A: 7 / -2 -> -3 (3 subtractions) A: 0 / 5 -> 0 (0 subtractions) A: -2147483648 / -1 -> 2147483647 (0 subtractions) A: -2147483648 / 1 would take 2,147,483,648 subtractions B: 5 + 9 -> 14 (9 increments) B: 1 + 2147483646 would take 2,147,483,646 increments
Recorded with Python 3.14.8 on macOS 26 arm64. To run it yourself: mise exec python@3.14.8 -- python3 brute_force.py
Runs on this device, in your browser. The first run downloads Python (about 13.5 MB), which is kept for the next runs.
Your run, in this browser
The quotient of −2³¹ / 1 takes 2,147,483,648 subtractions, about 21 seconds of C++ for a single call if a simple step costs 10 nanoseconds, the rough figure of the constraints lesson, and minutes of Python. Adding 2,147,483,646 by increments is just as slow. Both need a number of steps that grows with the size of the operands, where the target is a fixed 32 or so.
What to notice
- In A, each bit of the quotient is one yes-or-no question: does b · 2ᵏ still fit into what is left of a? Asked from k = 31 down, that is 32 questions.
- In B, a + b equals
(a ^ b) + ((a & b) << 1): the sum without carries plus the carries, which is another addition, with fewer carries each time. - Python’s integers have no width, so neither 32-bit overflow nor the end of the carries happens by itself: the code must keep 32 bits explicitly.
Long division in binary, proved with an invariant Pro: opens with a Pro, Premium or Ultimate pass
In this part:
- Signs, rounding toward zero, and the one quotient that overflows
- Adding with XOR and carries, and why 32 rounds are enough
- Emulating 32-bit integers in Python and JavaScript
- The code in five languages
- Edge cases and common bugs
- Variants: multiplication, remainders and shifts that round toward zero
- Exercise: divide without the division operator
- Divide two 32-bit integers without *, / or %
- A practice set with sample answers
- Check yourself
- Interview questions
- How do you divide two non-negative integers with only shifts, subtraction and comparisons, and why does it take at most 32 steps for 32-bit values?
- Your divide-without-division solution passes the sample tests and fails hidden ones. Which inputs are dangerous for 32-bit signed integers, what do Java, C++, Go, JavaScript and Python do with each, and how does your code handle them?
- A Python function adds two integers without + by repeating a, b = a ^ b, (a & b) << 1 until b is 0. It works for positive numbers but never returns for add(-1, 1). Explain why, fix it for 32-bit semantics, and bound the number of rounds.
- A Java service computes the 32-bit FNV-1a hash of strings, multiplying by 16777619 in an int. The JavaScript port writes h = (h * 16777619) >>> 0 and gets the same hash for "a" but a different one for "hello". Why, and how do you fix the port?
- Key takeaways
8 runnable examples (C++, Go, Java, JavaScript, Python) · 1 exercise with sample tests · 3 interview answers · about 20 minutes
Opening this part with your pass…
This part opens with any MySmartCoPilot pass.
- Pro pass · 1 week₹79$2.99
- 30 days₹179$5.99
- 1 year₹1,699$45
One payment; a pass never renews. The price shown is the total you pay: no fees or charges are added at checkout.
Passes can’t be bought right now, so this part can’t be opened at the moment. The free part above stands on its own. If you have a pass, enter your licence key.
It also opens every other in-depth part in Learn and every Pro tool. Sales are final, except where the law gives you a right to withdraw, for example in the EU and the UK (refund policy).
References
- Numeric types: int, float, complex (The Python Standard Library: built-in types) (Python Software Foundation)
- Bitwise operations on integer types (The Python Standard Library: built-in types) (Python Software Foundation)
- The Java Language Specification, Java SE 25: 15.17.2 Division operator / (Oracle)
- Java SE 25 API: Math.abs(int) (Oracle)
- Arithmetic operators: overflows and division (cppreference.com) (cppreference.com)
- UndefinedBehaviorSanitizer (Clang documentation) (LLVM Project)
- The Go Programming Language Specification: integer operators (The Go Authors)
- ECMAScript language specification: Math.imul (Ecma International (TC39))
- ECMAScript language specification: ToInt32 (Ecma International (TC39))
Related tools
Report a problem with this lesson
Kept only in this browser. Your Learn progress