TheAlgorithms/Python · error · ValueError

multiplicative_persistence() only accepts integral values

Error message

multiplicative_persistence() only accepts integral values

What it means

multiplicative_persistence() in maths/persistence.py counts how many times you must multiply a number's digits together until one digit remains. It first requires the argument to be a Python int (isinstance(num, int)); anything else — strings, floats — raises ValueError('multiplicative_persistence() only accepts integral values'). The check runs before the negativity check, so a non-int negative-looking input hits this error first. The string-based digit loop (str(num), int(i)) is why non-integral types are rejected.

Source

Thrown at maths/persistence.py:20

    """
    Return the persistence of a given number.

    https://en.wikipedia.org/wiki/Persistence_of_a_number

    >>> multiplicative_persistence(217)
    2
    >>> multiplicative_persistence(-1)
    Traceback (most recent call last):
        ...
    ValueError: multiplicative_persistence() does not accept negative values
    >>> multiplicative_persistence("long number")
    Traceback (most recent call last):
        ...
    ValueError: multiplicative_persistence() only accepts integral values
    """

    if not isinstance(num, int):
        raise ValueError("multiplicative_persistence() only accepts integral values")
    if num < 0:
        raise ValueError("multiplicative_persistence() does not accept negative values")

    steps = 0
    num_string = str(num)

    while len(num_string) != 1:
        numbers = [int(i) for i in num_string]

        total = 1
        for i in range(len(numbers)):
            total *= numbers[i]

        num_string = str(total)

        steps += 1
    return steps

View on GitHub (pinned to f5988cc097)

Solutions

  1. Convert the argument with int() before calling: multiplicative_persistence(int(num)).
  2. Validate/parse external data at the system boundary rather than relying on the function's guard.
  3. Remember it raises ValueError (not TypeError) — catch accordingly.

Example fix

# before
multiplicative_persistence(user_input)  # ValueError for '7788'

# after
multiplicative_persistence(int(user_input))
Defensive patterns

Strategy: type-guard

Validate before calling

if not isinstance(num, int):
    raise ValueError(f'persistence needs int, got {type(num).__name__}')
multiplicative_persistence(num)

Type guard

def is_persistence_input(v) -> bool:
    return isinstance(v, int) and not isinstance(v, bool)

Try / catch

try:
    multiplicative_persistence(num)
except ValueError as exc:
    if 'integral values' in str(exc):
        num = int(num)
    else:
        raise

Prevention

When it happens

Trigger: Calling multiplicative_persistence('long number'), multiplicative_persistence(77.0), or passing an unparsed value from input()/JSON. Note the type check precedes the sign check, so multiplicative_persistence(-0.5) raises this, not the negative-values error.

Common situations: Chaining the function directly after input() or a web-form field without int() conversion; tests written with string literals ('39') copied from documentation examples.

Related errors


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