Skip to content

Compound Interest Calculator — Rust 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 Rust implementation — the same logic the interactive tool runs, in a shareable, citable form.

//! compound-interest-calculator — compound growth projection.
//!
//! Display snippet: ports the core `project` math from the TypeScript lib
//! (src/lib/interest.ts). 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 `None`
//! on invalid input (negative principal, negative years, unsupported
//! frequency, non-finite values). Standard library only.

/// Round to 2 decimals, half-up (mirrors the TS `Math.round`).
fn round2(n: f64) -> f64 {
    (n * 100.0 + 0.5).floor() / 100.0
}

pub fn project(principal: f64, rate_pct: f64, years: i64, compounds_per_year: u32) -> Option<f64> {
    let frequency_ok = matches!(compounds_per_year, 1 | 2 | 4 | 12 | 365);
    if !(principal.is_finite() && rate_pct.is_finite())
        || principal < 0.0
        || years < 0
        || !frequency_ok
    {
        return None;
    }

    let n = f64::from(compounds_per_year);
    let monthly_rate = (1.0 + rate_pct / 100.0 / n).powf(n / 12.0) - 1.0;

    let mut balance = principal;
    for _ in 0..years * 12 {
        balance *= 1.0 + monthly_rate;
    }
    Some(round2(balance))
}

// Example:
//   project(10000.0, 5.0, 10, 12) -> Some(16470.09)

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 →