{"record":{"id":"18bf8f0983d7727b","repo":"TheAlgorithms/Python","slug":"double-factorial-iterative-only-accepts-integral","errorCode":null,"errorMessage":"double_factorial_iterative() only accepts integral values","messagePattern":"double_factorial_iterative\\(\\) only accepts integral values","errorType":"exception","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"maths/double_factorial.py","lineNumber":48,"sourceCode":"    Compute double factorial using iterative method.\n\n    To learn about the theory behind this algorithm:\n    https://en.wikipedia.org/wiki/Double_factorial\n\n    >>> from math import prod\n    >>> all(double_factorial_iterative(i) == prod(range(i, 0, -2)) for i in range(20))\n    True\n    >>> double_factorial_iterative(0.1)\n    Traceback (most recent call last):\n        ...\n    ValueError: double_factorial_iterative() only accepts integral values\n    >>> double_factorial_iterative(-1)\n    Traceback (most recent call last):\n        ...\n    ValueError: double_factorial_iterative() not defined for negative values\n    \"\"\"\n    if not isinstance(num, int):\n        raise ValueError(\"double_factorial_iterative() only accepts integral values\")\n    if num < 0:\n        raise ValueError(\"double_factorial_iterative() not defined for negative values\")\n    value = 1\n    for i in range(num, 0, -2):\n        value *= i\n    return value\n\n\nif __name__ == \"__main__\":\n    import doctest\n\n    doctest.testmod()\n","sourceCodeStart":30,"sourceCodeEnd":61,"githubUrl":"https://github.com/TheAlgorithms/Python/blob/f5988cc09713315817df6a7e327e258013a94440/maths/double_factorial.py#L30-L61","documentation":"Raised by double_factorial_iterative() in maths/double_factorial.py when num is not an int. The iterative loop for i in range(num, 0, -2) requires an integer to build the range, so float inputs like 0.1 are rejected with ValueError up front rather than producing a confusing range TypeError.","triggerScenarios":"Calling double_factorial_iterative(0.1), double_factorial_iterative(7.0), or passing any non-int. The guard is not isinstance(num, int).","commonSituations":"Floats from arithmetic or deserialization (7.0 instead of 7); numpy scalars that are not plain int on some platforms; passing the result of a division like 14/2.","solutions":["Cast whole floats: double_factorial_iterative(int(num)) when num == int(num).","Prefer math.prod(range(int(num), 0, -2)) for tolerant/numpy-friendly inputs.","Keep values as ints through the pipeline; use // instead of / for integer division."],"exampleFix":"# before\ndouble_factorial_iterative(14 / 2)  # ValueError (7.0 is a float)\n\n# after\ndouble_factorial_iterative(14 // 2)  # int 7, returns 105","handlingStrategy":"type-guard","validationCode":"if not isinstance(num, int) or isinstance(num, bool):\n    if num != int(num):\n        raise ValueError('num must be integral')\n    num = int(num)","typeGuard":"def is_integral(n) -> bool:\n    return isinstance(n, int) or (isinstance(n, float) and n == int(n))","tryCatchPattern":"try:\n    r = double_factorial_iterative(num)\nexcept ValueError as e:\n    if 'integral values' in str(e):\n        r = double_factorial_iterative(int(num))\n    else:\n        raise","preventionTips":["Cast numpy ints with int() before calling — not all pass isinstance(x, int).","Prefer math.prod(range(n, 0, -2)) when input types are heterogeneous."],"tags":["maths","factorial","iterative","validation","valueerror"],"backgroundTag":null,"analyzedSha":"f5988cc09713315817df6a7e327e258013a94440","analyzedAt":"2026-08-14T17:30:07.041Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}