TheAlgorithms/Python · error · ValueError

factorial_recursive() only accepts integral values

Error message

factorial_recursive() only accepts integral values

What it means

Raised by factorial_recursive() in maths/factorial.py when the argument n is not an int (e.g. a float like 0.1, or a string). The function guards its recursive computation with an isinstance(n, int) check because the recursion n * factorial_recursive(n - 1) and the base case n in {0, 1} assume exact integer arithmetic. Note that bool passes this check since bool subclasses int, but any float, even 5.0, is rejected.

Source

Thrown at maths/factorial.py:56

def factorial_recursive(n: int) -> int:
    """
    Calculate the factorial of a positive integer
    https://en.wikipedia.org/wiki/Factorial

    >>> import math
    >>> all(factorial_recursive(i) == math.factorial(i) for i in range(20))
    True
    >>> factorial_recursive(0.1)
    Traceback (most recent call last):
        ...
    ValueError: factorial_recursive() only accepts integral values
    >>> factorial_recursive(-1)
    Traceback (most recent call last):
        ...
    ValueError: factorial_recursive() not defined for negative values
    """
    if not isinstance(n, int):
        raise ValueError("factorial_recursive() only accepts integral values")
    if n < 0:
        raise ValueError("factorial_recursive() not defined for negative values")
    return 1 if n in {0, 1} else n * factorial_recursive(n - 1)


if __name__ == "__main__":
    import doctest

    doctest.testmod()

    n = int(input("Enter a positive integer: ").strip() or 0)
    print(f"factorial{n} is {factorial(n)}")

View on GitHub (pinned to f5988cc097)

Solutions

  1. Coerce to int before calling: factorial_recursive(int(n)) when you know the value is integral (e.g. int(5.0)).
  2. Validate with isinstance(n, int) at the call site and surface your own error message for non-integral input.
  3. If you need gamma-function behavior for real numbers, use math.gamma(n + 1) instead of this function.
  4. Use math.factorial(n), which raises its own TypeError for non-integers, if you do not need the recursive implementation.

Example fix

# before
factorial_recursive(5.0)  # ValueError

# after
n = 5.0
if not isinstance(n, int):
    n = int(n)  # only if known integral
factorial_recursive(n)
Defensive patterns

Strategy: type-guard

Validate before calling

if not isinstance(n, int):
    if isinstance(n, float) and n.is_integer():
        n = int(n)
    else:
        raise TypeError(f'expected integer, got {type(n).__name__}')
result = factorial_recursive(n)

Type guard

def is_int_like(value: object) -> bool:
    return isinstance(value, int) and not isinstance(value, bool) or (
        isinstance(value, float) and value.is_integer()
    )

Try / catch

try:
    factorial_recursive(n)
except ValueError as exc:
    raise TypeError(f'bad factorial input {n!r}') from exc

Prevention

When it happens

Trigger: Calling factorial_recursive(0.1), factorial_recursive(5.0), factorial_recursive('5'), or passing a numpy float or Decimal value. Any non-int type reaches the `if not isinstance(n, int)` guard and raises ValueError before recursion starts.

Common situations: Passing user input parsed as float (float(input(...))), forwarding values from APIs that deserialize numbers as floats, mixing numpy scalar types into pure-Python math helpers, or forgetting that True/False are the only non-int values accepted.

Related errors


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