TheAlgorithms/Python · error · ValueError
daily_interest_rate must be >= 0
Error message
daily_interest_rate must be >= 0
What it means
Raised by simple_interest() in financial/interest.py when daily_interest_rate < 0. Zero rate is allowed (interest is then 0), but a negative rate would produce negative interest that the doctest contract does not model. It is the second check, so days_between_payments is already valid when it fires.
Source
Thrown at financial/interest.py:36
>>> simple_interest(5500.0, 0.01, 100)
5500.0
>>> simple_interest(10000.0, -0.06, 3)
Traceback (most recent call last):
...
ValueError: daily_interest_rate must be >= 0
>>> simple_interest(-10000.0, 0.06, 3)
Traceback (most recent call last):
...
ValueError: principal must be > 0
>>> simple_interest(5500.0, 0.01, -5)
Traceback (most recent call last):
...
ValueError: days_between_payments must be > 0
"""
if days_between_payments <= 0:
raise ValueError("days_between_payments must be > 0")
if daily_interest_rate < 0:
raise ValueError("daily_interest_rate must be >= 0")
if principal <= 0:
raise ValueError("principal must be > 0")
return principal * daily_interest_rate * days_between_payments
def compound_interest(
principal: float,
nominal_annual_interest_rate_percentage: float,
number_of_compounding_periods: float,
) -> float:
"""
>>> compound_interest(10000.0, 0.05, 3)
1576.2500000000014
>>> 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)View on GitHub (pinned to f5988cc097)
Solutions
- Pass the daily rate as a non-negative decimal fraction (0.0005 for 0.05%/day).
- If converting from an annual percentage, divide consistently and clamp at 0 only after confirming negatives are data errors.
- Validate rate >= 0 in your ingestion layer with a clear error naming the field.
Example fix
# before si = simple_interest(10000.0, -0.06, 3) # ValueError # after si = simple_interest(10000.0, 0.0006, 3)
Defensive patterns
Strategy: validation
Validate before calling
if daily_interest_rate < 0:
raise InputError("daily rate must be >= 0 as a decimal (0.0005 for 0.05%/day)") Type guard
def valid_non_negative_rate(r) -> bool:
return isinstance(r, (int, float)) and r >= 0 Try / catch
try:
si = simple_interest(principal, daily_rate, days)
except ValueError as exc:
raise InputError(str(exc)) from exc Prevention
- Keep rates as decimal fractions with a documented convention.
- Sanitize scraped rate strings (unicode minus, %, commas).
- Check magnitudes too: 6 instead of 0.06 silently overstates interest 100x.
When it happens
Trigger: simple_interest(10000.0, -0.06, 3); rates computed as (new_rate - old_rate) deltas; percent-to-decimal conversion bugs that introduce a sign.
Common situations: Passing 6 instead of 0.06 combined with a sign flip from discount arithmetic; negative promotional rates in product data; scraping a rate field that includes a unicode minus.
Related errors
- nominal_annual_interest_rate_percentage 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/19070c7ff5247841.
Report an issue: GitHub.