TheAlgorithms/Python · error · ValueError

num must be non-negative integer

Error message

num must be non-negative integer

What it means

Raised by integer_square_root in maths/integer_square_root.py when num is not an int or is negative. The function computes floor(sqrt(num)) via binary search, which is only defined for non-negative integers; a single guard rejects floats (even whole-valued ones like 2.0), strings, and negatives with ValueError. Use math.isqrt for an equivalent standard-library implementation.

Source

Thrown at maths/integer_square_root.py:48

    46340
    >>> from math import isqrt
    >>> all(integer_square_root(i) == isqrt(i) for i in range(20))
    True
    >>> integer_square_root(-1)
    Traceback (most recent call last):
        ...
    ValueError: num must be non-negative integer
    >>> integer_square_root(1.5)
    Traceback (most recent call last):
        ...
    ValueError: num must be non-negative integer
    >>> integer_square_root("0")
    Traceback (most recent call last):
        ...
    ValueError: num must be non-negative integer
    """
    if not isinstance(num, int) or num < 0:
        raise ValueError("num must be non-negative integer")

    if num < 2:
        return num

    left_bound = 0
    right_bound = num // 2

    while left_bound <= right_bound:
        mid = left_bound + (right_bound - left_bound) // 2
        mid_squared = mid * mid
        if mid_squared == num:
            return mid

        if mid_squared < num:
            left_bound = mid + 1
        else:
            right_bound = mid - 1

View on GitHub (pinned to f5988cc097)

Solutions

  1. Convert whole floats: call integer_square_root(int(num)) when num.is_integer().
  2. Clamp tiny negative round-off to 0: num = max(0, num) when the value is mathematically non-negative.
  3. Prefer the standard library's math.isqrt, which has the same int-only requirement but is faster and battle-tested.

Example fix

// before
root = integer_square_root(x)  # x is 16.0 after float math

// after
root = integer_square_root(int(round(x)))  # or math.isqrt(int(x))
Defensive patterns

Strategy: validation

Validate before calling

if isinstance(num, float):
    if not num.is_integer():
        raise ValueError(f"not a whole number: {num}")
    num = int(num)
if num < 0:
    num = 0  # only if mathematically safe to clamp
root = integer_square_root(num)

Type guard

def is_nonneg_int(v) -> bool:
    return isinstance(v, int) and not isinstance(v, bool) and v >= 0

Try / catch

try:
    r = integer_square_root(x)
except ValueError:
    r = math.isqrt(max(0, int(x)))

Prevention

When it happens

Trigger: Calling integer_square_root(-1), integer_square_root(1.5), integer_square_root(2.0), or integer_square_root('0'). The guard 'if not isinstance(num, int) or num < 0' catches all of these; note 0 and 1 are fine (num < 2 returns num).

Common situations: Passing floats from division or numpy computations where a whole float (16.0) was expected to be accepted; string input from parsing; negative values arising from floating-point round-off on what should be non-negative computed quantities.

Related errors


AI-assisted analysis of TheAlgorithms/Python@f5988cc097 (2026-08-14). Data as JSON: /api/errors/9def63240f29910a. Report an issue: GitHub.