Something like that was what I was envisioning (of course the inability to represent NaN or infinity with a BigDecimal is annoying). To me this approach really only breaks down when you stop using an actual iteration to perform the computation… as long as a “sum” in some form is part of the internal state then this still works.
> On Apr 12, 2017, at 12:27 PM, Peter Levart <peter.lev...@gmail.com> wrote: > > > > On 04/12/2017 04:41 PM, Peter Levart wrote: >> On 04/11/2017 10:48 PM, Chris Dennis wrote: >>> Color me confused… what would the javadoc on the parameter say? It could I >>> guess have an @implNote documenting the meanings of the parameters… but >>> then what use is it? The proposed API simply limits the precision with >>> which a DoubleSummaryStatistic can be copied to be the same as the >>> precision with which it can be “accessed”. That doesn’t seem an enormous >>> problem since I suspect that bulk of usages would be to marshall a >>> “finished” instance and therefore there is no real loss occuring. If we >>> wanted to support arbitrary precision wouldn’t it be better to have a >>> constructor variant that took a BigDecimal, and a matching getPreciseSum() >>> that returned a BigDecimal? >> >> And how would you compute the value for BigDecimal getPreciseSum() so that >> you could then set 3 internal double fields from BigDecimal without loss of >> information? > > > ...perhaps we could use the BigDecimal getPreciseSum() together with getSum() > to reconstruct the state. For exmaple: > > /** > * Construct an instance with values obtained from another instance. > * > * @param count what was returned from another instance's {@link > #getCount()} > * @param sum what was returned from another instance's {@link #getSum()} > * @param preciseSum what was returned from another instance's {@link > #getPreciseSum()} > * @param min what was returned from another instance's {@link #getMin()} > * @param max what was returned from another instance's {@link #getMax()} > */ > public DoubleSummaryStatistics(long count, > double sum, BigDecimal preciseSum, > double min, double max) { > if (count < 0L) { > throw new IllegalArgumentException("count < 0"); > } else if (count > 0L) { > if (min > max) { > throw new IllegalArgumentException("min > max"); > } > this.count = count; > this.min = min; > this.max = max; > setSum(sum, preciseSum); > } > } > > /** > * If {@link #getSum()} returns {@link Double#NaN} or {@link > Double#POSITIVE_INFINITY} > * or {@link Double#NEGATIVE_INFINITY}, then this method returns {@code > null}, > * otherwise it returns a value that is a more precise representation of > the > * sum of values recorded and can be used in > * {@link #DoubleSummaryStatistics(long, double, BigDecimal, double, > double)} > * to construct an object with internal state that closely resembles the > state of > * original object. > * > * @return a precise sum in BigDecimal form. > */ > public final BigDecimal getPreciseSum() { > double sum = getSum(); > if (Double.isNaN(sum) || Double.isInfinite(sum)) { > return null; > } else { > return new BigDecimal(this.sum).add( > new BigDecimal(this.sumCompensation)); > } > } > > private void setSum(double sum, BigDecimal preciseSum) { > if (preciseSum == null) { > if (!Double.isNaN(sum) && !Double.isInfinite(sum)) { > throw new IllegalArgumentException( > "preciseSum is null but sum is not a NaN and not > Infinite"); > } > this.sum = this.simpleSum = sum; > this.sumCompensation = 0d; > } else { > if (Double.isNaN(sum) || Double.isInfinite(sum)) { > throw new IllegalArgumentException( > "preciseSum is non-null but sum is NaN or Infinite"); > } > this.sum = this.simpleSum = preciseSum.doubleValue(); > this.sumCompensation = preciseSum.subtract(new > BigDecimal(this.sum)).doubleValue(); > } > } > > > Hm.... > > > Regards, Peter >