Summary
Applying an affine transform to a uniform and spatially equidistributed random float/double in the range [0, 1) to obtain values in a user specified range [left, right), as currently done in the JDK, results in a slightly deformed distribution due to rounding error.
Problem
See JDK-8302987 for a more detailed description of the problem.
Solution
Add a new public API point to java.util.random.RandomGenerator to obtain a stream that generates a uniform and equidistributed flow of doubles in a given interval.
Specification
+ /**
+ * Returns an effectively unlimited stream of pseudorandomly chosen
+ * {@code double} values, where each value is between the specified
+ * {@code left} boundary and the specified {@code right} boundary.
+ * The {@code left} boundary is included as indicated by
+ * {@code isLeftIncluded}; similarly, the {@code right} boundary is included
+ * as indicated by {@code isRightIncluded}.
+ *
+ * <p>The stream potentially produces all multiples <i>k</i> δ
+ * (<i>k</i> integer) lying in the interval specified by the parameters,
+ * where δ > 0 is the smallest number for which all these multiples
+ * are exact {@code double}s.
+ * They are therefore all equidistant.
+ * The uniformity of the distribution of the {@code double}s produced by
+ * the stream depends on the quality of the underlying {@link #nextLong(long)}.
+ *
+ * @implSpec The default implementation first determines the δ above.
+ * It then computes both the smallest integer <i>k</i><sub><i>l</i></sub>
+ * such that <i>k</i><sub><i>l</i></sub> δ lies <em>inside</em>
+ * the given interval, and the smallest integer <i>n</i> > 0 such that
+ * (<i>k</i><sub><i>l</i></sub> + <i>n</i>) δ lies
+ * <em>outside</em> the interval.
+ * Finally, it returns a stream which generates the {@code double}s
+ * according to (<i>k</i><sub><i>l</i></sub> + {@code nextLong(}<i>n</i>{@code )})
+ * δ.
+ * The stream never produces {@code -0.0}, although it may produce
+ * {@code 0.0} if the specified interval contains 0.
+ *
+ * @param left the left boundary
+ * @param right the right boundary
+ * @param isLeftIncluded whether the {@code left} boundary is included
+ * @param isRightIncluded whether the {@code right} boundary is included
+ *
+ * @return a stream of pseudorandomly chosen {@code double} values, each
+ * between {@code left} and {@code right}, as specified above.
+ *
+ * @throws IllegalArgumentException if {@code left} is not finite,
+ * or {@code right} is not finite, or if the specified interval
+ * is empty.
+ */
+ default DoubleStream equiDoubles(double left, double right,
+ boolean isLeftIncluded, boolean isRightIncluded) {
- csr of
-
JDK-8302987 Add uniform and spatially equidistributed bounded double streams to RandomGenerator
- Resolved