Skip to content

Mortgage Calculator — C source

Compute monthly payments, the full amortization schedule and total interest, with extra-payment what-if analysis showing months and interest saved — runs entirely in your browser.

This is the C implementation — the same logic the interactive tool runs, in a shareable, citable form.

/*
 * mortgage-calculator — amortized monthly payment.
 *
 * Language: C (C11, standard library only)
 * Source:   CosmoDev polyglot showcase port of the Mortgage Calculator
 *           tool, ported from src/lib/mortgage.ts (the canonical
 *           TypeScript implementation).
 * Tool:     https://dev.cosmolabs.org/tools/mortgage-calculator
 * License:  display source — part of CosmoDev's polyglot tool pages.
 *
 * Display snippet: ports the core monthlyPayment() formula from the
 * TypeScript lib. The full amortization schedule (integer-cent tracking,
 * extra payments, payoff dates) lives in the TypeScript/Go sources.
 *
 * Semantics: standard amortization formula P*r*(1+r)^n / ((1+r)^n - 1)
 * with r = ratePct/100/12 and n = years*12. A zero rate divides the
 * principal evenly across n months. C has no Option type, so
 * monthly_payment() writes the result through an out-parameter and
 * returns false on invalid input (non-positive principal, non-positive
 * years, non-finite values).
 */

#include <assert.h>
#include <math.h>
#include <stdio.h>

/* Round to 2 decimals, half-up (mirrors the TS Math.round). */
static double round2(double n)
{
    return floor(n * 100.0 + 0.5) / 100.0;
}

/* Returns 1 and writes *out on success, 0 on invalid input. */
static int monthly_payment(double principal, double rate_pct, int years,
                           double *out)
{
    if (!isfinite(principal) || !isfinite(rate_pct))
        return 0;
    if (principal <= 0.0 || years <= 0)
        return 0;

    double r = rate_pct / 100.0 / 12.0;
    double n = (double)years * 12.0;

    double payment;
    if (r == 0.0) {
        payment = principal / n;
    } else {
        double growth = pow(1.0 + r, n);
        payment = principal * r * growth / (growth - 1.0);
    }
    *out = round2(payment);
    return 1;
}

int main(void)
{
    double out = 0.0;

    /* Example:
     *   monthly_payment(300000, 6, 30) -> 1798.65 */
    assert(monthly_payment(300000.0, 6.0, 30, &out));
    assert(out == 1798.65);

    /* A zero rate divides the principal evenly. */
    assert(monthly_payment(300000.0, 0.0, 30, &out));
    assert(out == 833.33);

    /* Invalid inputs are rejected, never clamped. */
    assert(!monthly_payment(-1.0, 6.0, 30, &out));          /* non-positive principal */
    assert(!monthly_payment(300000.0, 6.0, 0, &out));       /* non-positive years    */
    assert(!monthly_payment(INFINITY, 6.0, 30, &out));      /* non-finite value      */

    printf("ok\n");
    return 0;
}

Also available in 13 other languages

Every CosmoDev tool ships its pure logic in TypeScript (web) and Go (CLI), with authored implementations in a dozen-plus languages — the same contract, ported. Compare all languages side by side →