Integer Square Root by Binary Search

Compute the floor of the square root of a nonnegative integer using binary search.

Integer Square Root by Binary Search

Integer square root by binary search computes the largest integer $r$ such that:

$$ r^2 \le n $$

For a nonnegative integer $n$, this value is written as:

$$ \lfloor \sqrt{n} \rfloor $$

The algorithm avoids floating point arithmetic and gives an exact integer result.

Problem

Given a nonnegative integer $n$, find the largest integer $r$ such that:

$$ r^2 \le n $$

Equivalently:

$$ r = \lfloor \sqrt{n} \rfloor $$

Key Idea

The predicate:

$$ m^2 \le n $$

is monotone over nonnegative integers.

It has the form:

$$ true, true, true, false, false, false $$

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 ans

Example

Let:

$$ n = 27 $$

We need the largest $r$ such that:

$$ r^2 \le 27 $$

Check nearby values:

r r^2 valid
4 16 yes
5 25 yes
6 36 no

Therefore:

$$ \lfloor \sqrt{27} \rfloor = 5 $$

Correctness

The algorithm maintains ans as the largest valid value found so far.

If $m^2 \le n$, then $m$ 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 $m^2 > n$, then $m$ 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 $n$.

Complexity

cost value
iterations $O(\log n)$
time $O(\log n)$
space $O(1)$

Overflow Avoidance

In fixed-width integer languages, the expression:

m * m <= n

may overflow.

Use division instead:

m <= n // m

when $m > 0$.

This tests the same condition without multiplying two possibly large integers.

Optimized Bound

For $n \ge 2$, the square root is at most:

$$ \frac{n}{2} $$

So the initial range may be reduced to:

l = 1
r = n // 2

For simplicity, many implementations use $[0, n]$.

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 ans
func 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
}