TheAlgorithms/Python · error · Exception

Rate of interest must be >= 0

Error message

Rate of interest must be >= 0

What it means

Raised by equated_monthly_installments() in financial/equated_monthly_installments.py when rate_per_annum < 0. A negative nominal interest rate is rejected even though some real-world rates have gone negative, because the annuity formula and its doctests assume rate >= 0; zero is allowed (it degenerates to principal/number_of_payments). It is the second check, after principal.

Source

Thrown at financial/equated_monthly_installments.py:40

    >>> equated_monthly_installments(25000, 0.12, 10)
    358.67737100646826
    >>> equated_monthly_installments(0, 0.12, 3)
    Traceback (most recent call last):
        ...
    Exception: Principal borrowed must be > 0
    >>> equated_monthly_installments(25000, -1, 3)
    Traceback (most recent call last):
        ...
    Exception: Rate of interest must be >= 0
    >>> equated_monthly_installments(25000, 0.12, 0)
    Traceback (most recent call last):
        ...
    Exception: Years to repay must be an integer > 0
    """
    if principal <= 0:
        raise Exception("Principal borrowed must be > 0")
    if rate_per_annum < 0:
        raise Exception("Rate of interest must be >= 0")
    if years_to_repay <= 0 or not isinstance(years_to_repay, int):
        raise Exception("Years to repay must be an integer > 0")

    # Yearly rate is divided by 12 to get monthly rate
    rate_per_month = rate_per_annum / 12

    # Years to repay is multiplied by 12 to get number of payments as payment is monthly
    number_of_payments = years_to_repay * 12

    return (
        principal
        * rate_per_month
        * (1 + rate_per_month) ** number_of_payments
        / ((1 + rate_per_month) ** number_of_payments - 1)
    )


if __name__ == "__main__":

View on GitHub (pinned to f5988cc097)

Solutions

  1. Pass the annual nominal rate as a non-negative decimal (0.12 for 12%, not 12 or -0.12).
  2. If a negative rate is legitimate for your domain, special-case it: divide principal by the payment count instead of calling this function.
  3. Sanitize: `rate = abs(rate) if data_entry_sign_error else rate` only after confirming the sign is an artifact.

Example fix

# before
emi = equated_monthly_installments(25000, -1, 3)  # Exception

# after
emi = equated_monthly_installments(25000, 0.01, 3)  # 1% p.a.
Defensive patterns

Strategy: validation

Validate before calling

if rate_per_annum < 0:
    raise LoanInputError("annual rate must be >= 0 (decimal, e.g. 0.12 for 12%)")

Type guard

def valid_rate(r) -> bool:
    return isinstance(r, (int, float)) and r >= 0

Try / catch

try:
    emi = equated_monthly_installments(principal, rate, years)
except Exception as exc:
    raise LoanInputError(str(exc)) from exc  # bare Exception from library

Prevention

When it happens

Trigger: equated_monthly_installments(25000, -1, 3); rates parsed with a stray '-' sign; percent values like -0.12 instead of 0.12.

Common situations: Sign errors when subtracting discounts from a base rate; handling negative-rate mortgages (unsupported here — compute manually if truly needed); config files storing rates as strings with minus signs.

Related errors


AI-assisted analysis of TheAlgorithms/Python@f5988cc097 (2026-08-14). Data as JSON: /api/errors/6e2031e444d67518. Report an issue: GitHub.