TheAlgorithms/Python · error · ValueError
number_of_years must be > 0
Error message
number_of_years must be > 0
What it means
Raised by apr_interest() in financial/interest.py when number_of_years <= 0. The function computes annual-percentage-rate interest by delegating to compound_interest with number_of_years * 365 periods, so a non-positive year count is meaningless and rejected before any math runs. It is a deliberate input-contract check, not a numerical failure.
Source
Thrown at financial/interest.py:106
>>> apr_interest(10000.0, 0.05, 1)
512.6749646744732
>>> apr_interest(0.5, 0.05, 3)
0.08091115361317736
>>> apr_interest(10000.0, 0.06, -4)
Traceback (most recent call last):
...
ValueError: number_of_years must be > 0
>>> apr_interest(10000.0, -3.5, 3.0)
Traceback (most recent call last):
...
ValueError: nominal_annual_percentage_rate must be >= 0
>>> apr_interest(-5500.0, 0.01, 5)
Traceback (most recent call last):
...
ValueError: principal must be > 0
"""
if number_of_years <= 0:
raise ValueError("number_of_years must be > 0")
if nominal_annual_percentage_rate < 0:
raise ValueError("nominal_annual_percentage_rate must be >= 0")
if principal <= 0:
raise ValueError("principal must be > 0")
return compound_interest(
principal, nominal_annual_percentage_rate / 365, number_of_years * 365
)
if __name__ == "__main__":
import doctest
doctest.testmod()
View on GitHub (pinned to f5988cc097)
Solutions
- Pass a strictly positive number of years: at minimum 1 (or a positive fraction for partial years).
- If the value is user-supplied or computed, validate it at the call site before invoking apr_interest.
- If 0 years is legitimately possible in your flow, short-circuit it: return the principal unchanged instead of calling the function.
Example fix
# before apr_interest(10000.0, 0.05, end_year - start_year) # ValueError when equal # after years = end_year - start_year value = 10000.0 if years <= 0 else apr_interest(10000.0, 0.05, years)
Defensive patterns
Strategy: validation
Validate before calling
years = end_year - start_year
if years <= 0:
raise ValueError(f"term must be positive, got {years}")
apr_interest(10000.0, 0.05, years) Try / catch
try:
value = apr_interest(p, r, y)
except ValueError as exc:
if 'number_of_years' in str(exc):
raise ValueError(f'invalid term: {y}') from exc
raise Prevention
- Validate durations at the boundary where they are computed, not inside loops of financial calls.
- Remember the check order: years, then rate, then principal — fix the first bad argument first.
When it happens
Trigger: Calling apr_interest(principal, rate, years) with years = 0 or a negative value, e.g. apr_interest(10000.0, 0.01, 0) or apr_interest(10000.0, 0.01, -3). Note years is checked first, so a bad years value masks bad rate/principal.
Common situations: Passing a computed duration that can be 0 (e.g. (end_year - start_year) before validation), unit confusion (months passed where years expected, giving fractional-but-positive values that silently work), or defaults of 0 in a config dict.
Related errors
- nominal_annual_percentage_rate must be >= 0
- Discount rate cannot be negative
- Cash flows list cannot be empty
- Window size must be a positive integer
- Useful years cannot be less than 1
AI-assisted analysis of TheAlgorithms/Python@f5988cc097 (2026-08-14).
Data as JSON: /api/errors/ec629becf66ac95e.
Report an issue: GitHub.