{"record":{"id":"a99c32854c7a769d","repo":"TheAlgorithms/Python","slug":"multiplicative-persistence-does-not-accept-negat","errorCode":null,"errorMessage":"multiplicative_persistence() does not accept negative values","messagePattern":"multiplicative_persistence\\(\\) does not accept negative values","errorType":"exception","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"maths/persistence.py","lineNumber":22,"sourceCode":"\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\n\ndef additive_persistence(num: int) -> int:","sourceCodeStart":4,"sourceCodeEnd":40,"githubUrl":"https://github.com/TheAlgorithms/Python/blob/f5988cc09713315817df6a7e327e258013a94440/maths/persistence.py#L4-L40","documentation":"multiplicative_persistence() in maths/persistence.py rejects negative inputs after confirming the value is an int: if num < 0 it raises ValueError('multiplicative_persistence() does not accept negative values'). Digit-product persistence is defined for non-negative integers, and str(-39) would inject a '-' character that breaks the int(i) digit parsing, so negatives are refused rather than mangled.","triggerScenarios":"Calling multiplicative_persistence(-1) or any negative int such as multiplicative_persistence(-39). Only reached when the argument is an int; a negative float raises the integral-values error instead because the type check runs first.","commonSituations":"Feeding signed deltas or temperatures into the function; forgetting to abs() a value that can be negative by domain; off-by-one underflow producing -1 in a loop.","solutions":["Pass the absolute value if sign is irrelevant: multiplicative_persistence(abs(num)).","Add an upstream range check (num >= 0) with your own error message if negatives indicate a bug in caller data.","Catch ValueError if negative input is expected occasionally and handle it explicitly."],"exampleFix":"# before\nmultiplicative_persistence(value)  # ValueError when value == -39\n\n# after\nmultiplicative_persistence(abs(value))","handlingStrategy":"validation","validationCode":"if num < 0:\n    raise ValueError(f'persistence undefined for negative {num}')\nmultiplicative_persistence(num)","typeGuard":null,"tryCatchPattern":"try:\n    multiplicative_persistence(num)\nexcept ValueError as exc:\n    if 'negative' in str(exc):\n        num = abs(num)  # only if sign is truly irrelevant\n    else:\n        raise","preventionTips":["abs() signed values before digit math when sign is noise.","Treat a negative input as a data-quality bug and log it.","Validate numeric ranges at the boundary, not inside math loops."],"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"}