Skip to content

Compound Interest Calculator — C++ source

Project investment growth with any compounding frequency, scheduled contributions and inflation adjustment. Yearly breakdown, growth curve and CSV export — runs entirely in your browser.

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

// compound-interest-calculator — compound growth projection.
//
// Language: C++ (C++17, standard library only)
// Source:   CosmoDev polyglot showcase port of the Compound Interest
//           Calculator tool, ported from src/lib/interest.ts (the canonical
//           TypeScript implementation).
// Tool:     https://dev.cosmolabs.org/tools/compound-interest-calculator
// License:  display source — part of CosmoDev's polyglot tool pages.
//
// Display snippet: ports the core project() math from the TypeScript lib.
// The full projection (contributions, inflation, per-year rows) lives in
// the TypeScript/Go sources.
//
// Semantics: monthly simulation with the monthly rate set to the exact
// equivalent of the stated compounding frequency — (1 + r/n)^(n/12) - 1 —
// so the effective annual rate is preserved for every supported frequency.
// Returns the final balance rounded to 2 decimals, or std::nullopt on
// invalid input (negative principal, negative years, unsupported
// frequency, non-finite values).

#include <cassert>
#include <cmath>
#include <cstdint>
#include <cstdio>
#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;
}

bool frequency_ok(std::uint32_t compounds_per_year)
{
    switch (compounds_per_year) {
    case 1:
    case 2:
    case 4:
    case 12:
    case 365:
        return true;
    default:
        return false;
    }
}

std::optional<double> project(double principal, double rate_pct, std::int64_t years,
                              std::uint32_t compounds_per_year)
{
    if (!std::isfinite(principal) || !std::isfinite(rate_pct)) {
        return std::nullopt;
    }
    if (principal < 0.0 || years < 0 || !frequency_ok(compounds_per_year)) {
        return std::nullopt;
    }

    const double n = static_cast<double>(compounds_per_year);
    const double monthly_rate = std::pow(1.0 + rate_pct / 100.0 / n, n / 12.0) - 1.0;

    double balance = principal;
    for (std::int64_t i = 0; i < years * 12; ++i) {
        balance *= 1.0 + monthly_rate;
    }
    return round2(balance);
}

int main()
{
    // Example:
    //   project(10000, 5, 10, 12) -> 16470.09
    const auto result = project(10000.0, 5.0, 10, 12);
    assert(result.has_value());
    assert(*result == 16470.09);

    // Invalid inputs are rejected, never clamped.
    assert(!project(-1.0, 5.0, 10, 12));    // negative principal
    assert(!project(10000.0, 5.0, -1, 12)); // negative years
    assert(!project(10000.0, 5.0, 10, 6));  // unsupported frequency
    assert(!project(std::numeric_limits<double>::infinity(), 5.0, 10, 12)); // non-finite value

    std::puts("ok");
}

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 →