TheAlgorithms/Python · error · ValueError
nominal_annual_interest_rate_percentage must be >= 0
Error message
nominal_annual_interest_rate_percentage must be >= 0
What it means
Raised by compound_interest() in financial/interest.py when nominal_annual_interest_rate_percentage < 0. The parameter is expected as a decimal fraction per period (0.05 for 5%, per the doctest compound_interest(10000.0, 0.05, 3) => 1576.25); negative rates are rejected, and (1 + rate)**n would still be computable but is outside the modeled contract. It is the second check, after periods.
Source
Thrown at financial/interest.py:70
>>> 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)
1618.223072263547
>>> apr_interest(10000.0, 0.05, 1)View on GitHub (pinned to f5988cc097)
Solutions
- Pass the rate as a non-negative decimal fraction (0.05 for 5% per period).
- Sanitize market data: strip unicode minus, then check sign before calling.
- Double-check the unit: this parameter is a per-period decimal, so 5% monthly compounding uses 0.05, not 5.
Example fix
# before ci = compound_interest(10000.0, -3.5, 3.0) # ValueError # after ci = compound_interest(10000.0, 0.05, 3.0) # matches doctest: 1576.25...
Defensive patterns
Strategy: validation
Validate before calling
if nominal_annual_interest_rate_percentage < 0:
raise InputError("rate must be >= 0 as a decimal fraction (0.05 for 5%)") Type guard
def valid_rate(r) -> bool:
return isinstance(r, (int, float)) and r >= 0 Try / catch
try:
ci = compound_interest(principal, rate, periods)
except ValueError as exc:
raise InputError(str(exc)) from exc Prevention
- Pass 0.05 for 5%, per the doctest — verify magnitude as well as sign.
- Strip sign artifacts from spread-based rate fields before calling.
- Centralize percent->decimal conversion in one helper.
When it happens
Trigger: compound_interest(10000.0, -3.5, 3.0); passing -0.05 from a sign-flipped discount computation; passing a percentage like -5 instead of -0.05 (the latter raises, the magnitude error does not — see tips).
Common situations: Sign errors when rates are stored as spreads (lend minus borrow); negative central-bank rates in market data feeds; unicode minus signs from scraped tables.
Related errors
- daily_interest_rate must be >= 0
- days_between_payments must be > 0
- principal must be > 0
- number_of_compounding_periods must be > 0
- Principal borrowed must be > 0
AI-assisted analysis of TheAlgorithms/Python@f5988cc097 (2026-08-14).
Data as JSON: /api/errors/7f262f4bc39cae83.
Report an issue: GitHub.