TheAlgorithms/Python · error · NotImplementedError
num must be an integer or a half-integer
Error message
num must be an integer or a half-integer
What it means
Raised by gamma_recursive in maths/gamma.py when the fractional part of num is neither 0 nor 0.5. The recursion only has base cases for integers and half-integers (num == 0.5 returns sqrt(pi), num == 1 returns 1.0), so any other fractional input cannot terminate correctly and is rejected with NotImplementedError. This is an intentional API limitation, not a bug.
Source
Thrown at maths/gamma.py:100
>>> gamma_recursive(-4)
Traceback (most recent call last):
...
ValueError: math domain error
>>> gamma_recursive(172)
Traceback (most recent call last):
...
OverflowError: math range error
>>> gamma_recursive(1.1)
Traceback (most recent call last):
...
NotImplementedError: num must be an integer or a half-integer
"""
if num <= 0:
raise ValueError("math domain error")
if num > 171.5:
raise OverflowError("math range error")
elif num - int(num) not in (0, 0.5):
raise NotImplementedError("num must be an integer or a half-integer")
elif num == 0.5:
return math.sqrt(math.pi)
else:
return 1.0 if num == 1 else (num - 1) * gamma_recursive(num - 1)
if __name__ == "__main__":
from doctest import testmod
testmod()
num = 1.0
while num:
num = float(input("Gamma of: "))
print(f"gamma_iterative({num}) = {gamma_iterative(num)}")
print(f"gamma_recursive({num}) = {gamma_recursive(num)}")
print("\nEnter 0 to exit...")
View on GitHub (pinned to f5988cc097)
Solutions
- Use gamma_iterative(num) or math.gamma(num) for arbitrary positive floats.
- If you expect an integer/half-integer but floats drift in, round to the nearest 0.5 before calling: num = round(num * 2) / 2.
- Catch NotImplementedError explicitly to detect unsupported inputs in generic pipelines.
Example fix
// before val = gamma_recursive(3.3) # NotImplementedError // after from maths.gamma import gamma_iterative val = gamma_iterative(3.3) # supports any positive float
Defensive patterns
Strategy: fallback
Validate before calling
num = round(num * 2) / 2 # snap to nearest half-integer if drift expected
if num <= 0 or num > 171.5:
raise ValueError(f"out of range: {num}") Type guard
def is_supported_gamma_input(num) -> bool:
return 0 < num <= 171.5 and (num - int(num)) in (0, 0.5) Try / catch
try:
val = gamma_recursive(num)
except NotImplementedError:
val = gamma_iterative(num) # handles arbitrary positive floats Prevention
- Do not assume gamma_recursive equals math.gamma in domain
- Snap floating-point drift to the nearest 0.5 before calling if exact half-integers are expected
When it happens
Trigger: Calling gamma_recursive(1.1), gamma_recursive(2.7), or any value where num - int(num) is not 0 or 0.5. Note the check happens after the num <= 0 and num > 171.5 checks.
Common situations: Assuming gamma_recursive has the same domain as math.gamma or gamma_iterative (which accept any positive float); passing computed floating-point values that pick up small fractional residues (e.g. 2.0000000001 after arithmetic); testing with arbitrary decimals.
Related errors
- math domain error
- math range error
- mod inverse of {a!r} and {m!r} does not exist
- factorial() not defined for negative values
- Limit for the Catalan sequence must be ≥ 0
AI-assisted analysis of TheAlgorithms/Python@f5988cc097 (2026-08-14).
Data as JSON: /api/errors/203131415f27f10f.
Report an issue: GitHub.