TheAlgorithms/Python · error · ValueError

Input must be a positive number.

Error message

Input must be a positive number.

What it means

Raised by fast_inverse_sqrt() in maths/fast_inverse_sqrt.py when the input number is <= 0. The function implements the Quake III fast inverse square root via bit-level struct reinterpretation, and the magic-constant trick is only meaningful for positive, finite IEEE-754 floats; zero and negatives have no real inverse square root.

Source

Thrown at maths/fast_inverse_sqrt.py:39

    >>> fast_inverse_sqrt(4)
    0.49915357479239103
    >>> fast_inverse_sqrt(4.1)
    0.4932849504615651
    >>> fast_inverse_sqrt(0)
    Traceback (most recent call last):
        ...
    ValueError: Input must be a positive number.
    >>> fast_inverse_sqrt(-1)
    Traceback (most recent call last):
        ...
    ValueError: Input must be a positive number.
    >>> from math import isclose, sqrt
    >>> all(isclose(fast_inverse_sqrt(i), 1 / sqrt(i), rel_tol=0.00132)
    ...     for i in range(50, 60))
    True
    """
    if number <= 0:
        raise ValueError("Input must be a positive number.")
    i = struct.unpack(">i", struct.pack(">f", number))[0]
    i = 0x5F3759DF - (i >> 1)
    y = struct.unpack(">f", struct.pack(">i", i))[0]
    return y * (1.5 - 0.5 * number * y * y)


if __name__ == "__main__":
    from doctest import testmod

    testmod()
    # https://en.wikipedia.org/wiki/Fast_inverse_square_root#Accuracy
    from math import sqrt

    for i in range(5, 101, 5):
        print(f"{i:>3}: {(1 / sqrt(i)) - fast_inverse_sqrt(i):.5f}")

View on GitHub (pinned to f5988cc097)

Solutions

  1. Guard inputs: skip or clamp values <= 0 before calling (e.g. treat 0 magnitude as a special case).
  2. Use max(number, 1e-12) style epsilon flooring when near-zero magnitudes are expected.
  3. For exact (rather than approximate) results use 1 / math.sqrt(number), which still requires number > 0.
  4. Validate data upstream so zero/negative magnitudes never reach the routine.

Example fix

# before
inv_len = fast_inverse_sqrt(x*x + y*y)  # raises when vector is (0, 0)

# after
mag_sq = x*x + y*y
if mag_sq <= 0:
    inv_len = 0.0
else:
    inv_len = fast_inverse_sqrt(mag_sq)
Defensive patterns

Strategy: validation

Validate before calling

if number <= 0:
    raise ValueError(f'fast_inverse_sqrt requires positive input, got {number}')
result = fast_inverse_sqrt(number)

Type guard

def is_positive_finite(x: object) -> bool:
    import math
    return isinstance(x, (int, float)) and math.isfinite(x) and x > 0

Try / catch

try:
    y = fast_inverse_sqrt(x)
except ValueError:
    y = 0.0  # degenerate vector / non-positive magnitude fallback

Prevention

When it happens

Trigger: Calling fast_inverse_sqrt(0), fast_inverse_sqrt(-1), or fast_inverse_sqrt(-0.5). The `if number <= 0` guard raises ValueError before the struct pack/unpack bit hack runs.

Common situations: Normalizing zero-length vectors (1/sqrt(0) is infinite), passing unnormalized sensor data containing zeros, sign errors when squaring/absolute values are omitted, or feeding NaN-adjacent computed magnitudes into graphics or physics code.

Related errors


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