--- old/src/share/classes/java/util/DoubleSummaryStatistics.java 2013-11-20 00:17:18.000000000 -0800 +++ new/src/share/classes/java/util/DoubleSummaryStatistics.java 2013-11-20 00:17:18.000000000 -0800 @@ -63,6 +63,7 @@ public class DoubleSummaryStatistics implements DoubleConsumer { private long count; private double sum; + private double sumCompensation; // Low order bits of sum private double min = Double.POSITIVE_INFINITY; private double max = Double.NEGATIVE_INFINITY; @@ -81,7 +82,7 @@ @Override public void accept(double value) { ++count; - sum += value; + sumWithCompensation(value); min = Math.min(min, value); max = Math.max(max, value); } @@ -95,12 +96,24 @@ */ public void combine(DoubleSummaryStatistics other) { count += other.count; - sum += other.sum; + sumWithCompensation(other.sum); + sumWithCompensation(other.sumCompensation); min = Math.min(min, other.min); max = Math.max(max, other.max); } /** + * Incorporate a new double value using Kahan summation / + * compensated summation. + */ + private void sumWithCompensation(double value) { + double tmp = value - sumCompensation; + double velvel = sum + tmp; // Little wolf of rounding error + sumCompensation = (velvel - sum) - tmp; + sum = velvel; + } + + /** * Return the count of values recorded. * * @return the count of values