# Debt payoff calculator

See how many months a balance takes to clear at a fixed monthly payment, and what extra payments would save.

/**
 * Calculator maths for costreference.com.
 *
 * Plain functions on `window.CRCALC`. This file is the single source of the maths: it is
 * served to the browser as the calculator bundle and it is the file the Node test
 * (scripts/test-tool-math.mjs) imports. The tests therefore exercise exactly the code users run.
 *
 * Every function validates its inputs and returns NaN rather than throwing, so a bad input
 * produces an error message instead of a broken page.
 */
(function (root) {
  "use strict";

  function isNum(v) { return typeof v === "number" && Number.isFinite(v); }

  /** Standard amortising payment. i = monthly rate, n = months. */
  function monthlyPayment(principal, annualRatePct, months) {
    if (!isNum(principal) || !isNum(annualRatePct) || !isNum(months)) return NaN;
    if (principal  balance) princ = balance;
      if (princ  1e-9) cheaper = a  0
        ? Math.abs(a - b) / Math.max(a, b) * 100 : 0 };
  }

  /** Months to clear a balance at a fixed payment, plus the effect of paying more. */
  function payoffMonths(balance, annualRatePct, payment) {
    if (!isNum(balance) || !isNum(annualRatePct) || !isNum(payment)) return null;
    if (balance

      Balance owed (USD)

      Annual interest rate (%)

      Monthly payment (USD)

      Extra payment per month (USD)

  Calculate payoff

The calculator solves for the number of months needed to amortise a balance at a
fixed payment, then repeats the calculation with the extra payment added. If the payment does not
cover the first month's interest the balance never clears, and the calculator says so instead of
printing a number — that is the trap the minimum payment on a high-rate card sets.

(function () {
  var C = window.CRCALC;
  function $(id) { return document.getElementById(id); }
  function num(id) { var el = $(id); if (!el) return NaN; var v = el.value === "" ? NaN : Number(el.value); return Number.isFinite(v) ? v : NaN; }
  function money(n) { return "$" + n.toLocaleString("en-US", { minimumFractionDigits: 0, maximumFractionDigits: 0 }); }
  function render() {
    var bal = num("dp-balance"), rate = num("dp-rate"), pay = num("dp-payment"), extra = num("dp-extra");
    var err = $("dp-err"), out = $("dp-out");
    err.hidden = true;
    if (!Number.isFinite(bal) || bal  100) { err.hidden = false; err.textContent = "Enter an annual rate between 0 and 100."; out.innerHTML = ""; return; }
    if (!Number.isFinite(pay) || pay This payment never clears the balance

At " + rate + "% the first month's interest alone is " + money(bal * rate / 100 / 12) + ", and a payment of " + money(pay) + " does not cover it. The balance grows every month. Increase the payment above that figure.

";
      return;
    }
    var withExtra = C.payoffMonths(bal, rate, pay + extra);
    var rows = "Current payment" + money(pay) + "" + base.months + "" + money(base.interest) + "

";
    var savingLine = "";
    if (extra > 0 && withExtra && withExtra.clears) {
      rows += "With " + money(extra) + " extra" + money(pay + extra) + "" + withExtra.months + "" + money(withExtra.interest) + "

";
      savingLine = "Paying " + money(extra) + " extra clears the balance " + (base.months - withExtra.months) + " months sooner and saves " + money(base.interest - withExtra.interest) + " in interest.

";
    }
    out.innerHTML = "" + base.months + " months to clear

" +
      "At " + money(pay) + " per month you repay " + money(bal + base.interest) + " in total, of which " + money(base.interest) + " is interest.

" + savingLine +
      "Payoff comparisonScenarioMonthly paymentMonthsInterest paid

" + rows + "

";
  }
  window.__crRender = render;
  $("dp-go").addEventListener("click", render);
  ["dp-balance", "dp-rate", "dp-payment", "dp-extra"].forEach(function (id) { $(id).addEventListener("input", render); });
  render();
})();

Source: https://costreference.com/tools/debt-payoff-calculator/
