package com.plectix.simulator.util;
/**
*
* Keeps track of mean and stdev as you go along. Does not store the values. You
* can ask at any point what the mean and stdev of the added values are.
* The stdev formula divides by n-1 (raw score stdev), not n (population stdev).
*
*/
final class RunningMetric {
private String name = null;
private double n = 0;
private double sum = 0;
private double absoluteSum = 0;
private double sumSquare = 0;
private double sumCube = 0;
private double min = Double.POSITIVE_INFINITY;
private double max = Double.NEGATIVE_INFINITY;
public RunningMetric() {
reset();
}
public RunningMetric(String name) {
this.name = name;
reset();
}
/**
* Resets - as if no values have been added
*/
final void reset() {
n = sum = absoluteSum = sumSquare = sumCube = 0;
min = Double.POSITIVE_INFINITY;
max = Double.NEGATIVE_INFINITY;
}
/**
* Contributes this new value to the mean and stdev
*/
public final void add(double newValue) {
n++;
sum += newValue;
absoluteSum += Math.abs(newValue);
double square = newValue * newValue;
sumSquare += square;
sumCube += (newValue * square);
if (newValue < min)
min = newValue;
if (newValue > max)
max = newValue;
}
/**
* Contributes the values from another RunningMetric
*/
public final void add(RunningMetric runningMetric) {
n += runningMetric.n;
sum += runningMetric.sum;
absoluteSum += runningMetric.absoluteSum;
sumSquare += runningMetric.sumSquare;
sumCube += runningMetric.sumCube;
if (min > runningMetric.min)
min = runningMetric.min;
if (max < runningMetric.max)
max = runningMetric.max;
}
/**
* The mean thusfar of all values that have been added
*/
final double getAverage() {
if (n == 0)
return 0;
else
return sum / n;
}
/**
* The mean thusfar of all values that have been added
*/
public final double getMean() {
return getAverage();
}
/**
* The absolute mean thusfar of all values that have been added
*/
public final double getAbsoluteAverage() {
if (n == 0)
return 0;
else
return absoluteSum / n;
}
/**
* The variance of all values that have been added (sample variance)
*/
final double getVariance() {
if (n < 2)
return 0;
else {
return (n * sumSquare - sum * sum) / (n * (n - 1));
}
}
/**
* The standard deviation of all values that have been added
*/
public final double getStd() {
return Math.sqrt(getVariance());
}
/**
* The skewness of all values that have been added (sample skewness)
*/
final double getSkewness() {
if (n < 3) {
return 0;
} else {
double std = getStd();
if (std == 0.0) {
return 0.0;
}
double average = getAverage();
double numerator = sumCube + (2.0*n*average*average - 3.0*sumSquare) * average;
return (n * numerator) / ((n-1) * (n-2) * std * std * std);
}
}
/**
* The minimum of all values that have been added
*/
public final double getMin() {
return min;
}
/**
* The maximum of all values that have been added
*/
public final double getMax() {
return max;
}
/**
* The sum of all values that have been added
*/
public final double getSum() {
return sum;
}
/**
* The number of values added
*/
public final double getN() {
return n;
}
/**
* A string representation of: name, n(), sum(), min(), max(), mean(), std()
*/
@Override
public final String toString() {
return name + ": n=" + n + ", sum=" + sum + ", min=" + min + ", max=" + max
+ ", avg=" + getAverage() + ", std=" + getStd() + ", skew=" + getSkewness();
}
}