This is an automated email from the ASF dual-hosted git repository. khmarbaise pushed a commit to branch STATISTICS-14 in repository https://gitbox.apache.org/repos/asf/commons-statistics.git
commit 4e65221a692dbf8346d2ac9ca9958a6e879b4da5 Author: Karl Heinz Marbaise <khmarba...@apache.org> AuthorDate: Sat Jun 1 21:45:41 2019 +0200 [STATISTICS-14] - BigDecimalStatistics --- .../distribution/BigDecimalConsumer.java | 31 +++ .../distribution/BigDecimalSummaryStatistics.java | 208 +++++++++++++++++++++ .../BigDecimalSummaryStatisticsTest.java | 59 ++++++ 3 files changed, 298 insertions(+) diff --git a/commons-statistics-distribution/src/main/java/org/apache/commons/statistics/distribution/BigDecimalConsumer.java b/commons-statistics-distribution/src/main/java/org/apache/commons/statistics/distribution/BigDecimalConsumer.java new file mode 100644 index 0000000..51da71e --- /dev/null +++ b/commons-statistics-distribution/src/main/java/org/apache/commons/statistics/distribution/BigDecimalConsumer.java @@ -0,0 +1,31 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.commons.statistics.distribution; + +import java.math.BigDecimal; + +@FunctionalInterface +public interface BigDecimalConsumer { + + /** + * Performs this operation on the given argument. + * + * @param value the input argument + */ + void accept(BigDecimal value); + +} diff --git a/commons-statistics-distribution/src/main/java/org/apache/commons/statistics/distribution/BigDecimalSummaryStatistics.java b/commons-statistics-distribution/src/main/java/org/apache/commons/statistics/distribution/BigDecimalSummaryStatistics.java new file mode 100644 index 0000000..0a51329 --- /dev/null +++ b/commons-statistics-distribution/src/main/java/org/apache/commons/statistics/distribution/BigDecimalSummaryStatistics.java @@ -0,0 +1,208 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.commons.statistics.distribution; + +import java.math.BigDecimal; + +/** + * Implementation for BigDecimalSummaryStatistics based on {@link java.util.DoubleSummaryStatistics}. + */ +public class BigDecimalSummaryStatistics implements BigDecimalConsumer { + + /** + * internal counter. + */ + private Long count; + /** + * The total. + */ + private BigDecimal sum; + /** + * The minimum. + */ + private BigDecimal min; + /** + * The maximum. + */ + private BigDecimal max; + + /** + * Create an instance of BigDecimalSummaryStatistics. {@code count = 0} and sum = {@link + * BigDecimal#ZERO} + */ + public BigDecimalSummaryStatistics() { + this.count = Long.valueOf(0L); + this.sum = BigDecimal.ZERO; + this.max = null; + this.min = null; + } + + /** + * Constructs a non-empty instance with the specified {@code count}, {@code min}, {@code max}, + * and {@code sum}. + * + * <p>If {@code count} is zero then the remaining arguments are ignored and + * an empty instance is constructed. + * + * <p>If the arguments are inconsistent then an {@code IllegalArgumentException} + * is thrown. The necessary consistent argument conditions are: + * <ul> + * <li>{@code count >= 0}</li> + * <li>{@code min <= max}</li> + * </ul> + * + * @param count the count of values + * @param min the minimum value + * @param max the maximum value + * @param sum the sum of all values + * @throws IllegalArgumentException if the arguments are inconsistent + */ + public BigDecimalSummaryStatistics(Long count, BigDecimal min, BigDecimal max, + BigDecimal sum) throws IllegalArgumentException { + // FIXME: check for null in count, max, min, sum! + this.count = count; + this.sum = sum; + this.min = min; + this.max = max; + if (count < 0L) { + throw new IllegalArgumentException("Negative count value"); + } else if (count > 0L) { + if (min.compareTo(max) > 0) { + throw new IllegalArgumentException("Minimum greater than maximum"); + } + + this.count = count; + this.sum = sum; + this.min = min; + this.max = max; + } + } + + /** + * Records a new {@code BigDecimal} value into the summary information. + * + * @param value the input value + */ + @Override + public void accept(BigDecimal value) { + count++; + sum = sum.add(value); + + min = min == null ? value : min.min(value); + max = max == null ? value : max.max(value); + } + + /** + * Combines the state of another {@code BigDecimalSummaryStatistics} into this one. + * + * @param other another {@code LongSummaryStatistics} + * @throws IllegalArgumentException if {@code other} is null + */ + public void combine(BigDecimalSummaryStatistics other) throws IllegalArgumentException { + if (other == null) { + throw new IllegalArgumentException("other is not allowed to be null."); + } + + count++; + sum = sum.add(other.sum); + + min = min == null ? other.min : min.min(other.min); + max = max == null ? other.max : max.max(other.max); + } + + /** + * Returns the count of values recorded. + * + * @return the count of values + */ + public final Long getCount() { + return count; + } + + /** + * Returns the sum of values recorded, or zero if no values have been recorded. + * + * @return the sum of values, or zero if none + */ + public final BigDecimal getSum() { + return sum; + } + + /** + * Returns the minimum value recorded, or {@code ??????} if no values have been recorded. + * + * @return the minimum value, or {@link BigDecimal#???} if none + * FIXME: What to do if no call of accept/combine has happened yet? + */ + public final BigDecimal getMin() { + if (min == null) { + //TODO: Think about this! + return BigDecimal.valueOf(Double.NEGATIVE_INFINITY); + } else { + return min; + } + } + + /** + * Returns the maximum value recorded, or {@code XXXX} if no values have been recorded. + * + * @return the maximum value, or {@code XXXX} if none + * FIXME: What to do if no call of accept/combine has happened yet? + */ + public final BigDecimal getMax() { + if (max == null) { + //TODO: Think about this! + return BigDecimal.valueOf(Double.POSITIVE_INFINITY); + } else { + return max; + } + } + + /** + * Returns the arithmetic mean of values recorded, or zero if no values have been recorded. + * + * @return The arithmetic mean of values, or zero if none + */ + public final BigDecimal getAverage() { + if (getCount() > 0) { + BigDecimal bsum = getSum(); + Long bcount = getCount(); + return bsum.divide(BigDecimal.valueOf(bcount)); + } else { + return BigDecimal.ZERO; + } + } + + /** + * Returns a non-empty string representation of this object suitable for debugging. The exact + * presentation format is unspecified and may vary between implementations and versions. + */ + @Override + public String toString() { + return String.format( + "%s{count=%s, sum=%s, min=%s, average=%s, max=%s}", + this.getClass() + .getSimpleName(), + getCount().toString(), + getSum().toString(), + getMin().toString(), + getAverage().toString(), + getMax().toString() + ); + } + +} diff --git a/commons-statistics-distribution/src/test/java/org/apache/commons/statistics/distribution/BigDecimalSummaryStatisticsTest.java b/commons-statistics-distribution/src/test/java/org/apache/commons/statistics/distribution/BigDecimalSummaryStatisticsTest.java new file mode 100644 index 0000000..e39e067 --- /dev/null +++ b/commons-statistics-distribution/src/test/java/org/apache/commons/statistics/distribution/BigDecimalSummaryStatisticsTest.java @@ -0,0 +1,59 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.commons.statistics.distribution; + +import java.math.BigDecimal; +import java.util.stream.LongStream; +import org.junit.Assert; +import org.junit.Test; + +/** + * The Unit Test for {@link BigDecimalSummaryStatistics}. + */ +public class BigDecimalSummaryStatisticsTest { + + private static final double EPSILON = 1E-15d; + + @Test + public void theFirstTenElementsShouldCombinedIntoTotal() { + BigDecimalSummaryStatistics collect = + LongStream.rangeClosed(1, 10) + .mapToObj(BigDecimal::valueOf) + .collect(BigDecimalSummaryStatistics::new, + BigDecimalSummaryStatistics::accept, + BigDecimalSummaryStatistics::combine); + + Assert.assertEquals(5.5d, collect.getAverage().doubleValue(), EPSILON); + Assert.assertEquals(55d, collect.getSum().doubleValue(), EPSILON); + Assert.assertEquals(10L, collect.getCount().longValue()); + Assert.assertEquals(1L, collect.getMin().longValue()); + Assert.assertEquals(10L, collect.getMax().longValue()); + } + + @Test + public void standardDeviationBigDecimal() { + BigDecimalSummaryStatistics collect = + LongStream.rangeClosed(10, 2_000_000) + .mapToObj(BigDecimal::valueOf) + .collect(BigDecimalSummaryStatistics::new, + BigDecimalSummaryStatistics::accept, + BigDecimalSummaryStatistics::combine); + System.out.println("Collect:" + collect); + } + + +}