TheAlgorithms/Python · error · ValueError

additive_persistence() only accepts integral values

Error message

additive_persistence() only accepts integral values

What it means

additive_persistence() in maths/persistence.py counts how many times you must sum a number's digits until one digit remains. Like its multiplicative sibling, it first requires isinstance(num, int); strings, floats, and other types raise ValueError('additive_persistence() only accepts integral values'). The type check precedes the sign check, so any non-int input — including negative floats — triggers this error rather than the negative-values error.

Source

Thrown at maths/persistence.py:59

    """
    Return the persistence of a given number.

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

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

    if not isinstance(num, int):
        raise ValueError("additive_persistence() only accepts integral values")
    if num < 0:
        raise ValueError("additive_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 = 0
        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 first: additive_persistence(int(num)).
  2. Parse and type-check data at ingestion (API edge, file read) so math helpers always receive ints.
  3. Catch ValueError, not TypeError, around these calls.

Example fix

# before
additive_persistence(raw)  # ValueError when raw is '1234'

# after
additive_persistence(int(raw))
Defensive patterns

Strategy: type-guard

Validate before calling

if not isinstance(num, int):
    num = int(num)
additive_persistence(num)

Type guard

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

Try / catch

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

Prevention

When it happens

Trigger: Calling additive_persistence('long number'), additive_persistence(123.0), or passing a value straight from input()/a deserialized payload. Booleans pass (bool subclasses int).

Common situations: Forwarding raw form/query-parameter strings into math helpers; refactoring older code that used len(str(num)) on flexible types; catching TypeError while the function actually raises ValueError.

Related errors


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