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++ (C++17, 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. Returns the payment rounded to
// cents, or std::nullopt on invalid input (non-positive principal,
// non-positive years, non-finite values).

#include <cassert>
#include <cmath>
#include <iostream>
#include <limits>
#include <optional>

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

std::optional<double> monthlyPayment(double principal, double ratePct, int years)
{
    if (!std::isfinite(principal) || !std::isfinite(ratePct))
        return std::nullopt;
    if (principal <= 0.0 || years <= 0)
        return std::nullopt;

    const double r = ratePct / 100.0 / 12.0;
    const double n = static_cast<double>(years) * 12.0;

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

int main()
{
    // Example:
    //   monthlyPayment(300000, 6, 30) -> 1798.65
    auto result = monthlyPayment(300000.0, 6.0, 30);
    assert(result && *result == 1798.65);

    // A zero rate divides the principal evenly.
    assert(monthlyPayment(300000.0, 0.0, 30).value_or(-1) == 833.33);

    // Invalid inputs are rejected, never clamped.
    assert(!monthlyPayment(-1.0, 6.0, 30).has_value());         // non-positive principal
    assert(!monthlyPayment(300000.0, 6.0, 0).has_value());      // non-positive years
    assert(!monthlyPayment(std::numeric_limits<double>::infinity(), 6.0, 30).has_value()); // non-finite

    std::cout << "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 →