You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@commons.apache.org by ah...@apache.org on 2021/12/16 12:17:49 UTC
[commons-statistics] 03/05: Avoid overflow in the continuous uniform distribution
This is an automated email from the ASF dual-hosted git repository.
aherbert pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/commons-statistics.git
commit aaf91eb83012564a9f1f1c67c0f1d20ebf7921a6
Author: aherbert <ah...@apache.org>
AuthorDate: Thu Dec 16 11:18:25 2021 +0000
Avoid overflow in the continuous uniform distribution
The range (upper - lower) must be finite for the current implementation
to function. If infinite (or nan) then throw an exception.
Ensure the mean is robust to overflow if (lower + upper) is infinite.
---
.../distribution/UniformContinuousDistribution.java | 17 +++++++++++------
.../distribution/UniformContinuousDistributionTest.java | 9 +++++++++
2 files changed, 20 insertions(+), 6 deletions(-)
diff --git a/commons-statistics-distribution/src/main/java/org/apache/commons/statistics/distribution/UniformContinuousDistribution.java b/commons-statistics-distribution/src/main/java/org/apache/commons/statistics/distribution/UniformContinuousDistribution.java
index 84b35f7..d9acb29 100644
--- a/commons-statistics-distribution/src/main/java/org/apache/commons/statistics/distribution/UniformContinuousDistribution.java
+++ b/commons-statistics-distribution/src/main/java/org/apache/commons/statistics/distribution/UniformContinuousDistribution.java
@@ -54,7 +54,8 @@ public final class UniformContinuousDistribution extends AbstractContinuousDistr
* @param lower Lower bound of this distribution (inclusive).
* @param upper Upper bound of this distribution (inclusive).
* @return the distribution
- * @throws IllegalArgumentException if {@code lower >= upper}.
+ * @throws IllegalArgumentException if {@code lower >= upper} or the range between the bounds
+ * is not finite
*/
public static UniformContinuousDistribution of(double lower,
double upper) {
@@ -62,6 +63,9 @@ public final class UniformContinuousDistribution extends AbstractContinuousDistr
throw new DistributionException(DistributionException.INVALID_RANGE_LOW_GTE_HIGH,
lower, upper);
}
+ if (!Double.isFinite(upper - lower)) {
+ throw new DistributionException("Range %s is not finite", upper - lower);
+ }
return new UniformContinuousDistribution(lower, upper);
}
@@ -150,19 +154,20 @@ public final class UniformContinuousDistribution extends AbstractContinuousDistr
/**
* {@inheritDoc}
*
- * <p>For lower bound {@code lower} and upper bound {@code upper}, the mean is
- * {@code 0.5 * (lower + upper)}.
+ * <p>For lower bound {@code a} and upper bound {@code b}, the mean is
+ * {@code 0.5 * (a + b)}.
*/
@Override
public double getMean() {
- return 0.5 * (lower + upper);
+ // Avoid overflow
+ return 0.5 * lower + 0.5 * upper;
}
/**
* {@inheritDoc}
*
- * <p>For lower bound {@code lower} and upper bound {@code upper}, the
- * variance is {@code (upper - lower)^2 / 12}.
+ * <p>For lower bound {@code a} and upper bound {@code b}, the
+ * variance is {@code (b - a)^2 / 12}.
*/
@Override
public double getVariance() {
diff --git a/commons-statistics-distribution/src/test/java/org/apache/commons/statistics/distribution/UniformContinuousDistributionTest.java b/commons-statistics-distribution/src/test/java/org/apache/commons/statistics/distribution/UniformContinuousDistributionTest.java
index 28b384a..c56fde0 100644
--- a/commons-statistics-distribution/src/test/java/org/apache/commons/statistics/distribution/UniformContinuousDistributionTest.java
+++ b/commons-statistics-distribution/src/test/java/org/apache/commons/statistics/distribution/UniformContinuousDistributionTest.java
@@ -48,6 +48,10 @@ class UniformContinuousDistributionTest extends BaseContinuousDistributionTest {
return new Object[][] {
{0.0, 0.0},
{1.0, 0.0},
+ // Range not finite
+ {-Double.MAX_VALUE, Double.MAX_VALUE},
+ {Double.NaN, 1.0},
+ {0.0, Double.NaN},
};
}
@@ -69,6 +73,11 @@ class UniformContinuousDistributionTest extends BaseContinuousDistributionTest {
dist = UniformContinuousDistribution.of(-1.5, 0.6);
Assertions.assertEquals(-0.45, dist.getMean());
Assertions.assertEquals(0.3675, dist.getVariance());
+
+ // Overflow of 0.5 * (lower + upper)
+ dist = UniformContinuousDistribution.of(Double.MAX_VALUE / 2, Double.MAX_VALUE);
+ Assertions.assertEquals(Double.MAX_VALUE - Double.MAX_VALUE / 4, dist.getMean());
+ Assertions.assertEquals(Double.POSITIVE_INFINITY, dist.getVariance());
}
/**