TheAlgorithms/Python · error · ValueError

factorial() only accepts integral values

Error message

factorial() only accepts integral values

What it means

Raised by factorial() in maths/factorial.py when number != int(number) — i.e. the argument has a fractional part. The iterative loop for i in range(1, number + 1) needs a whole number; unlike isinstance-based guards this one accepts float types as long as the value is integral (5.0 passes, 5.5 raises).

Source

Thrown at maths/factorial.py:29

    >>> all(factorial(i) == math.factorial(i) for i in range(20))
    True
    >>> factorial(0.1)
    Traceback (most recent call last):
        ...
    ValueError: factorial() only accepts integral values
    >>> factorial(-1)
    Traceback (most recent call last):
        ...
    ValueError: factorial() not defined for negative values
    >>> factorial(1)
    1
    >>> factorial(6)
    720
    >>> factorial(0)
    1
    """
    if number != int(number):
        raise ValueError("factorial() only accepts integral values")
    if number < 0:
        raise ValueError("factorial() not defined for negative values")
    value = 1
    for i in range(1, number + 1):
        value *= i
    return value


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):

View on GitHub (pinned to f5988cc097)

Solutions

  1. Round or validate first: use factorial(int(number)) only when number == int(number).
  2. Prefer math.factorial, which raises a clear TypeError for floats entirely.
  3. Fix upstream arithmetic to use // or round deliberately rather than truncating silently.

Example fix

# before
factorial(7 / 2)  # 3.5 -> ValueError

# after
n = 7 // 2  # or round(7 / 2) if rounding is intended
factorial(n)
Defensive patterns

Strategy: validation

Validate before calling

if number != int(number):
    raise ValueError(f'factorial needs an integral value, got {number}')
number = int(number)

Type guard

def is_integral(n) -> bool:
    return n == int(n)

Try / catch

try:
    r = factorial(number)
except ValueError as e:
    if 'integral values' in str(e):
        raise ValueError(f'non-integral input {number} from upstream division') from e
    raise

Prevention

When it happens

Trigger: Calling factorial(5.5), factorial(-2.5), or any value whose int() truncation differs from itself. Note factorial(-3.0) passes this check and hits the negative-values ValueError next, and factorial('5') raises TypeError from the comparison, not this message.

Common situations: Floats produced by division (n / 2 for odd n), averaging, or numpy arithmetic; decoded JSON floats with fractional parts; passing a Decimal whose value is non-integral.

Related errors


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