Statistics Calculator — C++ source
Compute descriptive statistics - count, sum, mean, median, mode, min/max, range, variance, standard deviation, and quartiles (Q1/Q3/IQR) - from any list of numbers. Tolerates mixed separators and flags unparseable tokens. Choose sample (n−1) or population (n) variance. Everything runs 100% client-side.
This is the C++ implementation — the same logic the interactive tool runs, in a shareable, citable form.
// statistics — descriptive statistics over a free-form number list. Language: C++ (20). Port of src/lib/statistics.ts — same logic as this dir's python.py: comma/whitespace parse (finite only), R-7 interpolated quantiles, mode (empty when uniform), sample vs population variance.
#include <algorithm>
#include <cmath>
#include <iostream>
#include <limits>
#include <map>
#include <sstream>
#include <string>
#include <vector>
struct ParseResult { std::vector<double> values; std::vector<std::string> invalid; };
struct Stats { int count; double sum, mean, median, min, max, range, variance, stddev, q1, q3, iqr; std::vector<double> mode; };
constexpr double kNaN = std::numeric_limits<double>::quiet_NaN();
/* Split on comma/whitespace runs; only fully-parsed finite tokens count as values. */
static ParseResult parseNumbers(const std::string &input)
{
ParseResult r;
std::string s = input;
std::replace(s.begin(), s.end(), ',', ' ');
std::istringstream in(s);
std::string tok;
while (in >> tok) {
try {
size_t pos = 0;
double v = std::stod(tok, &pos); /* accepts inf/nan — filtered by isfinite */
if (pos == tok.size() && std::isfinite(v)) r.values.push_back(v);
else r.invalid.push_back(tok);
} catch (const std::exception &) { r.invalid.push_back(tok); } /* not a number at all */
}
return r;
}
/* Linear-interpolation quantile (R-7 / NumPy / Excel PERCENTILE) over ascending, non-empty data. */
static double quantile(const std::vector<double> &s, double p)
{
double h = (s.size() - 1) * p;
size_t lo = (size_t)std::floor(h), hi = (size_t)std::ceil(h);
return lo == hi ? s[lo] : s[lo] + (h - lo) * (s[hi] - s[lo]);
}
/* Most frequent value(s), ascending; empty when every distinct value ties (uniform). */
static std::vector<double> computeMode(const std::vector<double> &values)
{
std::map<double, int> freq; /* ordered keys → modes come out ascending */
for (double v : values) freq[v]++;
if (freq.size() == 1) return { values[0] };
int best = 0;
for (const auto &[v, c] : freq) best = std::max(best, c);
std::vector<double> modes;
for (const auto &[v, c] : freq)
if (c == best) modes.push_back(v);
return modes.size() == freq.size() ? std::vector<double>{} : modes;
}
static Stats summarize(const std::vector<double> &values, bool sample = true)
{
if (values.empty()) return { 0, kNaN, kNaN, kNaN, kNaN, kNaN, kNaN, kNaN, kNaN, kNaN, kNaN, kNaN, {} };
std::vector<double> s = values;
std::sort(s.begin(), s.end());
double sum = 0;
for (double v : values) sum += v; /* sum in original order */
double mean = sum / values.size(), ss = 0;
for (double v : values) ss += (v - mean) * (v - mean);
double variance = !sample ? ss / values.size()
: values.size() >= 2 ? ss / (values.size() - 1) : kNaN; /* population vs sample */
double q1 = quantile(s, 0.25), med = quantile(s, 0.5), q3 = quantile(s, 0.75);
return { (int)values.size(), sum, mean, med, s.front(), s.back(), s.back() - s.front(),
variance, std::sqrt(variance), q1, q3, q3 - q1, computeMode(values) };
}
int main()
{
auto [values, invalid] = parseNumbers("2, 4 4, 6, 8, 11, oops");
Stats st = summarize(values); /* sample=true — population: summarize(values, false) */
std::cout << "n=" << st.count << " sum=" << st.sum << " mean=" << st.mean
<< "\nmedian=" << st.median << " q1=" << st.q1 << " q3=" << st.q3 << " iqr=" << st.iqr
<< "\nmin=" << st.min << " max=" << st.max << " range=" << st.range
<< "\nvariance(sample)=" << st.variance << " stddev=" << st.stddev << "\nmode=[";
for (size_t i = 0; i < st.mode.size(); i++) std::cout << (i ? ", " : "") << st.mode[i];
std::cout << "] invalid=[";
for (size_t i = 0; i < invalid.size(); i++) std::cout << (i ? ", " : "") << invalid[i];
std::cout << "]\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 →