Summary
Remove restrictions on the size of the range of the two-argument forms of RandomGenerator.nextDouble
and RandomGenerator.nextFloat
.
Problem
The current spec requires the methods j.u.r.RandomGenerator.nextDouble(double,double)
and j.u.r.RandomGenerator.nextFloat(float,float)
to throw when the range [origin, bound) given by the arguments is so large that its size (bound - origin) overflows. For example, if origin = -Double.MAX_VALUE
and bound = Double.MAX_VALUE
, the current spec requires the methods to throw.
The proposed implementation doesn't suffer from this limitation. The example above would work as intuitively expected. It also returns the same results as the current implementation when the range size (bound - origin) does not overflow.
The API javadoc must match the extended behavior of the proposed implementation.
The same holds for the methods' spec in java.util.Random
and java.util.SplittableRandom
.
The j.u.r.RandomGenerator.doubles([long,]double,double)
methods depend on the above methods, which thus are adversely affected by the current behavior, as reported by the associated bug issue. The proposed implementation addresses this as well.
In addition, the spec in j.u.Random.doubles([long,]double,double)
contains code that does not reflect the proposed implementation and which should therefore be removed from the spec itself.
Solution
Modify the API spec.
Specification
--- a/src/java.base/share/classes/java/util/random/RandomGenerator.java
+++ b/src/java.base/share/classes/java/util/random/RandomGenerator.java
@@ -540,10 +540,7 @@ public interface RandomGenerator {
*
* @throws IllegalArgumentException if {@code origin} is not finite,
* or {@code bound} is not finite, or {@code origin}
- * is greater than or equal to {@code bound}, or
- * the difference between {@code bound} and {@code origin}
- * is so large that it cannot be represented as a finite
- * {@code float} value
+ * is greater than or equal to {@code bound}
*
* @implSpec The default implementation verifies that the {@code origin}
* and {@code bound} are valid then invokes {@code nextFloat()}
@@ -606,11 +603,8 @@ public interface RandomGenerator {
*
* @throws IllegalArgumentException if {@code origin} is not finite,
* or {@code bound} is not finite, or {@code origin}
- * is greater than or equal to {@code bound}, or
- * the difference between {@code bound} and {@code origin}
- * is so large that it cannot be represented as a finite
- * {@code double} value
- *
+ * is greater than or equal to {@code bound}
+
* @implSpec The default implementation verifies that the {@code origin}
* and {@code bound} are valid, then invokes {@code nextDouble()}
* scaling and translating the result to fit between {@code origin}
--- a/src/java.base/share/classes/java/util/Random.java
+++ b/src/java.base/share/classes/java/util/Random.java
@@ -598,12 +599,12 @@ public class Random implements RandomGenerator, java.io.Serializable {
* low-order bit of the significand would be 0 than that it would be 1.]
*
* @return the next pseudorandom, uniformly distributed {@code float}
- * value between {@code 0.0} and {@code 1.0} from this
+ * value between {@code 0.0f} and {@code 1.0f} from this
* random number generator's sequence
*/
@Override
public float nextFloat() {
}
/**
@@ -1070,26 +1071,12 @@ public class Random implements RandomGenerator, java.io.Serializable {
* pseudorandom {@code double} values, each conforming to the given origin
* (inclusive) and bound (exclusive).
*
- * <p>A pseudorandom {@code double} value is generated as if it's the result
- * of calling the following method with the origin and bound:
- * <pre> {@code
- * double nextDouble(double origin, double bound) {
- * double r = nextDouble();
- * r = r * (bound - origin) + origin;
- * if (r >= bound) // correct for rounding
- * r = Math.nextDown(bound);
- * return r;
- * }}</pre>
- *
* @param streamSize the number of values to generate
* @param randomNumberOrigin the origin (inclusive) of each random value
* @param randomNumberBound the bound (exclusive) of each random value
* @return a stream of pseudorandom {@code double} values,
* each with the given origin (inclusive) and bound (exclusive)
- * @throws IllegalArgumentException if {@code streamSize} is less than zero,
- * or {@code randomNumberOrigin} is not finite,
- * or {@code randomNumberBound} is not finite, or {@code randomNumberOrigin}
- * is greater than or equal to {@code randomNumberBound}
+ * @throws IllegalArgumentException {@inheritDoc}
* @since 1.8
*/
@Override
@@ -1101,18 +1088,7 @@ public class Random implements RandomGenerator, java.io.Serializable {
* Returns an effectively unlimited stream of pseudorandom {@code
* double} values, each conforming to the given origin (inclusive) and bound
* (exclusive).
- *
- * <p>A pseudorandom {@code double} value is generated as if it's the result
- * of calling the following method with the origin and bound:
- * <pre> {@code
- * double nextDouble(double origin, double bound) {
- * double r = nextDouble();
- * r = r * (bound - origin) + origin;
- * if (r >= bound) // correct for rounding
- * r = Math.nextDown(bound);
- * return r;
- * }}</pre>
- *
+
* @implNote This method is implemented to be equivalent to {@code
* doubles(Long.MAX_VALUE, randomNumberOrigin, randomNumberBound)}.
*
@@ -1120,8 +1096,7 @@ public class Random implements RandomGenerator, java.io.Serializable {
* @param randomNumberBound the bound (exclusive) of each random value
* @return a stream of pseudorandom {@code double} values,
* each with the given origin (inclusive) and bound (exclusive)
- * @throws IllegalArgumentException if {@code randomNumberOrigin}
- * is greater than or equal to {@code randomNumberBound}
+ * @throws IllegalArgumentException {@inheritDoc}
* @since 1.8
*/
@Override
--- a/src/java.base/share/classes/java/util/SplittableRandom.java
+++ b/src/java.base/share/classes/java/util/SplittableRandom.java
@@ -551,9 +551,7 @@ public final class SplittableRandom implements RandomGenerator, SplittableGenera
* @param randomNumberBound the bound (exclusive) of each random value
* @return a stream of pseudorandom {@code double} values,
* each with the given origin (inclusive) and bound (exclusive)
- * @throws IllegalArgumentException if {@code streamSize} is
- * less than zero, or {@code randomNumberOrigin}
- * is greater than or equal to {@code randomNumberBound}
+ * @throws IllegalArgumentException {@inheritDoc}
*/
@Override
public DoubleStream doubles(long streamSize, double randomNumberOrigin, double randomNumberBound) {
@@ -572,8 +570,7 @@ public final class SplittableRandom implements RandomGenerator, SplittableGenera
* @param randomNumberBound the bound (exclusive) of each random value
* @return a stream of pseudorandom {@code double} values,
* each with the given origin (inclusive) and bound (exclusive)
- * @throws IllegalArgumentException if {@code randomNumberOrigin}
- * is greater than or equal to {@code randomNumberBound}
+ * @throws IllegalArgumentException {@inheritDoc}
*/
@Override
public DoubleStream doubles(double randomNumberOrigin, double randomNumberBound) {
- csr of
-
JDK-8202449 overflow handling in Random.doubles
-
- Resolved
-
- relates to
-
JDK-8284357 Incorrect documentation of RandomGenerator.next(Float|Double)\(double, double\)
-
- Closed
-