{"record":{"id":"0b93392053ac17c7","repo":"TheAlgorithms/Python","slug":"multiplicative-persistence-only-accepts-integral","errorCode":null,"errorMessage":"multiplicative_persistence() only accepts integral values","messagePattern":"multiplicative_persistence\\(\\) only accepts integral values","errorType":"exception","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"maths/persistence.py","lineNumber":20,"sourceCode":"    \"\"\"\n    Return the persistence of a given number.\n\n    https://en.wikipedia.org/wiki/Persistence_of_a_number\n\n    >>> multiplicative_persistence(217)\n    2\n    >>> multiplicative_persistence(-1)\n    Traceback (most recent call last):\n        ...\n    ValueError: multiplicative_persistence() does not accept negative values\n    >>> multiplicative_persistence(\"long number\")\n    Traceback (most recent call last):\n        ...\n    ValueError: multiplicative_persistence() only accepts integral values\n    \"\"\"\n\n    if not isinstance(num, int):\n        raise ValueError(\"multiplicative_persistence() only accepts integral values\")\n    if num < 0:\n        raise ValueError(\"multiplicative_persistence() does not accept negative values\")\n\n    steps = 0\n    num_string = str(num)\n\n    while len(num_string) != 1:\n        numbers = [int(i) for i in num_string]\n\n        total = 1\n        for i in range(len(numbers)):\n            total *= numbers[i]\n\n        num_string = str(total)\n\n        steps += 1\n    return steps\n","sourceCodeStart":2,"sourceCodeEnd":38,"githubUrl":"https://github.com/TheAlgorithms/Python/blob/f5988cc09713315817df6a7e327e258013a94440/maths/persistence.py#L2-L38","documentation":"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.","triggerScenarios":"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.","commonSituations":"Chaining the function directly after input() or a web-form field without int() conversion; tests written with string literals ('39') copied from documentation examples.","solutions":["Convert the argument with int() before calling: multiplicative_persistence(int(num)).","Validate/parse external data at the system boundary rather than relying on the function's guard.","Remember it raises ValueError (not TypeError) — catch accordingly."],"exampleFix":"# before\nmultiplicative_persistence(user_input)  # ValueError for '7788'\n\n# after\nmultiplicative_persistence(int(user_input))","handlingStrategy":"type-guard","validationCode":"if not isinstance(num, int):\n    raise ValueError(f'persistence needs int, got {type(num).__name__}')\nmultiplicative_persistence(num)","typeGuard":"def is_persistence_input(v) -> bool:\n    return isinstance(v, int) and not isinstance(v, bool)","tryCatchPattern":"try:\n    multiplicative_persistence(num)\nexcept ValueError as exc:\n    if 'integral values' in str(exc):\n        num = int(num)\n    else:\n        raise","preventionTips":["Apply int() immediately after input()/deserialization.","Keep persistence math on ints end-to-end; avoid / division upstream.","Note the type guard fires before the negativity guard — order matters."],"tags":["python","value-error","input-validation","maths"],"backgroundTag":null,"analyzedSha":"f5988cc09713315817df6a7e327e258013a94440","analyzedAt":"2026-08-14T17:30:07.041Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}