Compute the floor of the square root of a nonnegative integer using binary search.
Integer square root by binary search computes the largest integer such that:
For a nonnegative integer , this value is written as:
The algorithm avoids floating point arithmetic and gives an exact integer result.
Problem
Given a nonnegative integer , find the largest integer such that:
Equivalently:
Key Idea
The predicate:
is monotone over nonnegative integers.
It has the form:
So we can binary search for the last true value.
Algorithm
integer_square_root(n):
l = 0
r = n
ans = 0
while l <= r:
m = l + (r - l) // 2
if m * m <= n:
ans = m
l = m + 1
else:
r = m - 1
return ansExample
Let:
We need the largest such that:
Check nearby values:
| r | r^2 | valid |
|---|---|---|
| 4 | 16 | yes |
| 5 | 25 | yes |
| 6 | 36 | no |
Therefore:
Correctness
The algorithm maintains ans as the largest valid value found so far.
If , then is a valid candidate, and any larger valid answer must lie to the right. The algorithm records ans = m and moves the left boundary to m + 1.
If , then and every larger value are invalid, so the algorithm moves the right boundary to m - 1.
When the search ends, all candidates have been classified. The stored ans is the largest integer whose square is at most .
Complexity
| cost | value |
|---|---|
| iterations | |
| time | |
| space |
Overflow Avoidance
In fixed-width integer languages, the expression:
m * m <= nmay overflow.
Use division instead:
m <= n // mwhen .
This tests the same condition without multiplying two possibly large integers.
Optimized Bound
For , the square root is at most:
So the initial range may be reduced to:
l = 1
r = n // 2For simplicity, many implementations use .
When to Use
Use integer square root when:
- exact integer arithmetic is required
- floating point rounding is unacceptable
- the input may be large
- you need a safe floor square root
Common uses include number theory, primality testing, integer geometry, and binary search exercises.
Implementation
def integer_square_root(n):
if n < 0:
raise ValueError("n must be nonnegative")
l, r = 0, n
ans = 0
while l <= r:
m = l + (r - l) // 2
if m == 0 or m <= n // m:
ans = m
l = m + 1
else:
r = m - 1
return ansfunc IntegerSquareRoot(n int) int {
if n < 0 {
return -1
}
l, r := 0, n
ans := 0
for l <= r {
m := l + (r-l)/2
if m == 0 || m <= n/m {
ans = m
l = m + 1
} else {
r = m - 1
}
}
return ans
}