-
Bug
-
Resolution: Fixed
-
P4
-
8, 11, 17, 18, 19
-
b08
-
generic
-
generic
-
Verified
Issue | Fix Version | Assignee | Priority | Status | Resolution | Resolved In Build |
---|---|---|---|---|---|---|
JDK-8281881 | 18.0.2 | Joe Darcy | P4 | Resolved | Fixed | b01 |
JDK-8281556 | 18.0.1 | Joe Darcy | P4 | Resolved | Fixed | b07 |
JDK-8285722 | 17.0.5-oracle | Ravi Reddy | P4 | Resolved | Fixed | b01 |
JDK-8288055 | 17.0.5 | Goetz Lindenmaier | P4 | Resolved | Fixed | b01 |
JDK-8280921 | 17.0.4-oracle | Ravi Reddy | P4 | Closed | Won't Fix | |
JDK-8280923 | 11.0.18-oracle | Ryan Wallace | P4 | Resolved | Fixed | b04 |
JDK-8296306 | 11.0.18 | Goetz Lindenmaier | P4 | Resolved | Fixed | b02 |
JDK-8280922 | 8u361 | Ryan Wallace | P4 | Resolved | Fixed | b04 |
Java 11.0.13
A DESCRIPTION OF THE PROBLEM :
The nextDouble​(double origin, double bound) method of java.util.SplittableRandom can return a result which is >= bound. According to the documentation (https://docs.oracle.com/en/java/javase/11/docs/api/java.base/java/util/SplittableRandom.html#nextDouble(double,double)), the result is < bound.
I believe the reason for this behavior is this line in the source: https://github.com/openjdk/jdk11u-dev/blob/master/src/java.base/share/classes/java/util/SplittableRandom.java#L353
r = Double.longBitsToDouble(Double.doubleToLongBits(bound) - 1);
This line probably wants to create a double less than bound by decrementing the result of Double.doubleToLongBits(bound). However, when bound is negative, decrementing the long will actually make the double bigger (due to 2's complement representation). The fix is possibly as simple as "+1" instead of "-1" when bound is negative.
I've tested this on Java 11, but looking at the source, newer versions are probably also affected: https://github.com/openjdk/jdk/blob/jdk-19+6/src/java.base/share/classes/jdk/internal/util/random/RandomSupport.java#L648
ThreadLocalRandom also seems to be affected.
STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
Compile and run the example code below.
EXPECTED VERSUS ACTUAL BEHAVIOR :
EXPECTED -
Expected output:
[some double which is between d1 (inclusive) and d2 (exclusive)]
true
true
ACTUAL -
Actual output:
-0.9999999999999999
true
false
---------- BEGIN SOURCE ----------
package com.example;
import java.util.SplittableRandom;
final class Example {
public static void main(String[] args) {
double d1 = -1.0000000000000002;
double d2 = -1.0;
var sr = new SplittableRandom(42L);
var r = sr.nextDouble(d1, d2);
System.out.println(r);
System.out.println(r >= d1);
System.out.println(r < d2);
}
}
---------- END SOURCE ----------
FREQUENCY : always
- backported by
-
JDK-8280922 SplittableRandom#nextDouble(double,double) can return result >= bound
- Resolved
-
JDK-8280923 SplittableRandom#nextDouble(double,double) can return result >= bound
- Resolved
-
JDK-8281556 SplittableRandom#nextDouble(double,double) can return result >= bound
- Resolved
-
JDK-8281881 SplittableRandom#nextDouble(double,double) can return result >= bound
- Resolved
-
JDK-8285722 SplittableRandom#nextDouble(double,double) can return result >= bound
- Resolved
-
JDK-8288055 SplittableRandom#nextDouble(double,double) can return result >= bound
- Resolved
-
JDK-8296306 SplittableRandom#nextDouble(double,double) can return result >= bound
- Resolved
-
JDK-8280921 SplittableRandom#nextDouble(double,double) can return result >= bound
- Closed
- duplicates
-
JDK-8282082 Bounded double values do not obey negative bounds
- Closed
- relates to
-
JDK-8296402 sun.awt.geom.Curve.next() and prev() wrap
- Open
-
JDK-8280950 RandomGenerator:NextDouble() default behavior non conformant after JDK-8280550 fix
- Closed
-
JDK-8281183 RandomGenerator:NextDouble() default behavior partially fixed by JDK-8280950
- Closed
- links to
-
Commit openjdk/jdk11u-dev/91f15382
-
Commit openjdk/jdk17u-dev/d16d4f1f
-
Commit openjdk/jdk18u/9d4b5edf
-
Commit openjdk/jdk/0c42e43f
-
Review openjdk/jdk11u-dev/1478
-
Review openjdk/jdk17u-dev/433
-
Review openjdk/jdk18u/21
-
Review openjdk/jdk/7221