Skip to content

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

// statistics — descriptive statistics over a free-form number list. Language: Java (17+). 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.
import java.util.*;

public class Statistics {
    record ParseResult(List<Double> values, List<String> invalid) {}
    record Stats(int count, double sum, double mean, double median, List<Double> mode,
                 double min, double max, double range, double variance, double stddev,
                 double q1, double q3, double iqr) {}

    /* Split on comma/whitespace runs; only fully-parsed finite tokens count as values. */
    static ParseResult parseNumbers(String input) {
        List<Double> values = new ArrayList<>();
        List<String> invalid = new ArrayList<>();
        for (String tok : input.replace(',', ' ').trim().split("\\s+")) {
            if (tok.isEmpty()) continue;
            try {
                double v = Double.parseDouble(tok); /* accepts inf/nan — filtered by isFinite */
                if (Double.isFinite(v)) values.add(v); else invalid.add(tok);
            } catch (NumberFormatException e) { invalid.add(tok); }
        }
        return new ParseResult(values, invalid);
    }

    /* Linear-interpolation quantile (R-7 / NumPy / Excel PERCENTILE) over ascending, non-empty data. */
    static double quantile(double[] s, double p) {
        double h = (s.length - 1) * p;
        int lo = (int) Math.floor(h), hi = (int) Math.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 List<Double> computeMode(List<Double> values) {
        TreeMap<Double, Integer> freq = new TreeMap<>(); /* sorted keys → modes come out ascending */
        for (double v : values) freq.merge(v, 1, Integer::sum);
        if (freq.size() == 1) return List.of(values.get(0)); /* a single distinct value is the mode */
        int best = Collections.max(freq.values());
        List<Double> modes = new ArrayList<>();
        for (Map.Entry<Double, Integer> e : freq.entrySet())
            if (e.getValue() == best) modes.add(e.getKey());
        return modes.size() == freq.size() ? List.of() : modes;
    }

    static Stats summarize(List<Double> values, boolean sample) {
        if (values.isEmpty())
            return new Stats(0, Double.NaN, Double.NaN, Double.NaN, List.of(), Double.NaN, Double.NaN,
                             Double.NaN, Double.NaN, Double.NaN, Double.NaN, Double.NaN, Double.NaN);
        double[] s = new double[values.size()];
        for (int i = 0; i < s.length; i++) s[i] = values.get(i);
        Arrays.sort(s);
        double sum = 0, mean, ss = 0;
        for (double v : values) sum += v; /* sum in original order */
        mean = sum / values.size();
        for (double v : values) ss += (v - mean) * (v - mean);
        /* Sample variance needs n >= 2; the population estimator always divides by n. */
        double variance = sample ? (values.size() >= 2 ? ss / (values.size() - 1) : Double.NaN)
                                 : ss / values.size();
        double q1 = quantile(s, 0.25), med = quantile(s, 0.5), q3 = quantile(s, 0.75);
        return new Stats(values.size(), sum, mean, med, computeMode(values), s[0], s[s.length - 1],
                         s[s.length - 1] - s[0], variance, Math.sqrt(variance), q1, q3, q3 - q1);
    }

    public static void main(String[] args) {
        ParseResult p = parseNumbers("2, 4 4, 6, 8, 11, oops");
        Stats st = summarize(p.values(), true); /* population: summarize(values, false) */
        System.out.printf("n=%d sum=%s mean=%s%nmedian=%s q1=%s q3=%s iqr=%s%nmin=%s max=%s range=%s%nvariance(sample)=%s stddev=%s%nmode=%s  invalid=%s%n",
                st.count(), st.sum(), st.mean(), st.median(), st.q1(), st.q3(), st.iqr(),
                st.min(), st.max(), st.range(), st.variance(), st.stddev(), st.mode(), p.invalid());
    }
}

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 →