package org.openlca.core.results; import java.util.ArrayList; import java.util.Collections; import java.util.List; /** * Calculates statistic parameters for a set of numbers. */ public class SimulationStatistics { private List<Double> values; private int intervalCount; private int[] frequencies; public SimulationStatistics(List<Double> values, int intervalCount) { if (values == null || values.isEmpty()) { this.values = new ArrayList<>(); this.values.add(0d); } else { this.values = new ArrayList<>(values); } Collections.sort(this.values); this.intervalCount = intervalCount < 1 ? 1 : intervalCount; calculateFrequencyTable(); } public static SimulationStatistics empty() { return new SimulationStatistics(null, 1); } private void calculateFrequencyTable() { frequencies = new int[intervalCount]; for (double val : values) { int idx = getInterval(val); frequencies[idx] += 1; } } /** * Get the zero-based index of the interval where the given value is * located. */ public int getInterval(double value) { double min = getMinimum(); double intervalRange = getRange() / intervalCount; int bucket = (int) ((value - min) / intervalRange); if (bucket > (intervalCount - 1)) return intervalCount - 1; return bucket; } public double getMaximum() { return values.get(values.size() - 1); } public double getMinimum() { return values.get(0); } public int getCount() { return values.size(); } public double getMean() { double sum = 0; for (double v : values) { sum += v; } return sum / values.size(); } /** * Returns the value at the given percentile. * * @param percentile * the percentage value (0..100) */ public double getPercentileValue(int percentile) { int index = percentile * values.size() / 100; if (index == 0 || 1 == (index % 2)) return values.get(index); return (values.get(index) + values.get(index - 1)) / 2; } public double getMedian() { int size = getCount(); if (size == 0) return 0; if (1 == (size % 2)) return values.get(size / 2); int upper = size / 2; int lower = upper - 1; return (values.get(upper) + values.get(lower)) / 2d; } public double getStandardDeviation() { if (values.size() < 2) return 0d; double mean = getMean(); double sd = 0d; for (double val : values) sd += Math.pow(val - mean, 2); sd /= values.size() - 1; return Math.sqrt(sd); } public double getRange() { return getMaximum() - getMinimum(); } public int getAbsoluteFrequency(int interval) { if (interval > (intervalCount - 1)) return 0; return frequencies[interval]; } public int getMaximalAbsoluteFrequency() { int maxFreq = frequencies[0]; for (int i = 1; i < frequencies.length; i++) maxFreq = Math.max(frequencies[i], maxFreq); return maxFreq; } }