package net.objectlab.kit.util;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.List;
import java.util.Optional;
public class PopulationStandardDeviation {
private final Average average = new Average();
private List<BigDecimal> dataPoints;
public Optional<BigDecimal> getMaximum() {
return average.getMaximum();
}
public BigDecimal getTotal() {
return average.getTotal();
}
public Optional<BigDecimal> getMinimum() {
return average.getMinimum();
}
public PopulationStandardDeviation add(final BigDecimal... values) {
if (values != null) {
average.add(values);
if (dataPoints == null) {
dataPoints = new ArrayList<>(values.length);
}
for (final BigDecimal val : values) {
dataPoints.add(val);
}
}
return this;
}
public BigDecimal getAverage() {
return average.getAverage();
}
public int getDataPoints() {
return average.getDataPoints();
}
public BigDecimal getStandardDeviation() {
if (dataPoints == null) {
return null;
}
final BigDecimal average = getAverage();
final BigDecimal sumSquaredDifferences = dataPoints.stream().map(dp -> BigDecimalUtil.subtract(dp, average).pow(2)).reduce(BigDecimal.ZERO,
(a, b) -> b != null ? a.add(b) : a);
final BigDecimal variance = BigDecimalUtil.divide(8, sumSquaredDifferences, BigDecimal.valueOf(getDataPointsForCalc()),
BigDecimal.ROUND_HALF_UP);
return variance == null ? null : BigDecimalUtil.setScale(BigDecimal.valueOf(Math.sqrt(variance.doubleValue())), 8);
}
protected long getDataPointsForCalc() {
return getDataPoints();
}
}