Compound Interest Calculator — Zig 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 Zig implementation — the same logic the interactive tool runs, in a shareable, citable form.
//! compound-interest-calculator — compound growth projection.
//!
//! Language: Zig (0.13, 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 `null`
//! on invalid input (negative principal, negative years, unsupported
//! frequency, non-finite values).
const std = @import("std");
/// Round to 2 decimals, half-up (mirrors the TS `Math.round`).
fn round2(n: f64) f64 {
return @floor(n * 100.0 + 0.5) / 100.0;
}
pub fn project(principal: f64, rate_pct: f64, years: i64, compounds_per_year: u32) ?f64 {
const frequency_ok = switch (compounds_per_year) {
1, 2, 4, 12, 365 => true,
else => false,
};
if (!std.math.isFinite(principal) or !std.math.isFinite(rate_pct) or
principal < 0 or years < 0 or !frequency_ok)
{
return null;
}
const n: f64 = @floatFromInt(compounds_per_year);
const monthly_rate = std.math.pow(f64, 1.0 + rate_pct / 100.0 / n, n / 12.0) - 1.0;
var balance = principal;
var i: i64 = 0;
while (i < years * 12) : (i += 1) {
balance *= 1.0 + monthly_rate;
}
return round2(balance);
}
pub fn main() void {
// Example:
// project(10000.0, 5.0, 10, 12) -> 16470.09
const result = project(10000.0, 5.0, 10, 12).?;
std.debug.assert(@abs(result - 16470.09) < 0.005);
// Invalid inputs are rejected, never clamped.
std.debug.assert(project(-1.0, 5.0, 10, 12) == null); // negative principal
std.debug.assert(project(10000.0, 5.0, -1, 12) == null); // negative years
std.debug.assert(project(10000.0, 5.0, 10, 6) == null); // unsupported frequency
std.debug.assert(project(std.math.inf(f64), 5.0, 10, 12) == null); // non-finite value
std.debug.print("ok\n", .{});
}
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 →