TheAlgorithms/Python · error · ValueError
number_of_compounding_periods must be > 0
Error message
number_of_compounding_periods must be > 0
What it means
Raised by compound_interest() in financial/interest.py when number_of_compounding_periods <= 0. The formula principal * ((1 + r)**n - 1) needs at least one compounding period to be meaningful; the check runs first, before rate and principal, so it fires even for otherwise-bad inputs.
Source
Thrown at financial/interest.py:68
>>> compound_interest(10000.0, 0.05, 1)
500.00000000000045
>>> compound_interest(0.5, 0.05, 3)
0.07881250000000006
>>> compound_interest(10000.0, 0.06, -4)
Traceback (most recent call last):
...
ValueError: number_of_compounding_periods must be > 0
>>> compound_interest(10000.0, -3.5, 3.0)
Traceback (most recent call last):
...
ValueError: nominal_annual_interest_rate_percentage must be >= 0
>>> compound_interest(-5500.0, 0.01, 5)
Traceback (most recent call last):
...
ValueError: principal must be > 0
"""
if number_of_compounding_periods <= 0:
raise ValueError("number_of_compounding_periods must be > 0")
if nominal_annual_interest_rate_percentage < 0:
raise ValueError("nominal_annual_interest_rate_percentage must be >= 0")
if principal <= 0:
raise ValueError("principal must be > 0")
return principal * (
(1 + nominal_annual_interest_rate_percentage) ** number_of_compounding_periods
- 1
)
def apr_interest(
principal: float,
nominal_annual_percentage_rate: float,
number_of_years: float,
) -> float:
"""
>>> apr_interest(10000.0, 0.05, 3)View on GitHub (pinned to f5988cc097)
Solutions
- Pass the total number of compounding periods, e.g. years * periods_per_year (12 for monthly over 3 years -> 36).
- Validate n > 0 upstream, especially when it is a computed product of two config values.
- For fractional-period needs, use a formula that supports continuous or fractional compounding instead of this function.
Example fix
# before ci = compound_interest(10000.0, 0.05, 0) # ValueError # after ci = compound_interest(10000.0, 0.05, 3 * 12) # monthly compounding for 3 years
Defensive patterns
Strategy: validation
Validate before calling
if number_of_compounding_periods <= 0:
raise InputError("periods must be >= 1; use years * periods_per_year") Type guard
def valid_periods(n) -> bool:
return isinstance(n, (int, float)) and n > 0 Try / catch
try:
ci = compound_interest(principal, rate, periods)
except ValueError as exc:
raise InputError(str(exc)) from exc Prevention
- Compute periods as years * frequency (e.g. 3 * 12), never pass frequency alone.
- Validate computed products of config values before calls.
- Do not pass a fractional interval (0.25) as the period count.
When it happens
Trigger: compound_interest(10000.0, 0.05, 0) or a negative period count; passing a period interval (e.g. 0.25 for quarterly) instead of the number of periods; counter variables that never increment because a loop body is skipped.
Common situations: Confusing compounding frequency (4 for quarterly) with total periods (years*4); off-by-one loops building amortization tables; defaults of 0 in config schemas.
Related errors
- days_between_payments must be > 0
- daily_interest_rate must be >= 0
- principal must be > 0
- nominal_annual_interest_rate_percentage must be >= 0
- Principal borrowed must be > 0
AI-assisted analysis of TheAlgorithms/Python@f5988cc097 (2026-08-14).
Data as JSON: /api/errors/702df2c67ef554c0.
Report an issue: GitHub.