The external evidence suggests we generate denormalized mantissa in Random.nextDouble(), which in turn skews the uniformity:
http://engineering.medallia.com/blog/2014/08/a-plea-for-an-equal-opportunity-random/
Comments
New random number generators subsumed under JDK-8248862.
Historical behavior will remain as documented.
02-03-2021
@Martin, recall that there are 2^53 double floating point numbers between 0.5 and 1, another 2^53 between 0.25 and 0.5, and so on. About half of double values are between 0 and 1.
My inclination is to clarify the docs in JDK 10 to more accurately characterize what the implementation does. Subclasses are encouraged to do a better job, etc.
17-05-2017
I've always thought that Random implementations should do a good job with all the java primitive types.
For j.u.Random I was annoyed that there were only 48 bits of seed, making nextLong a bit bogus.
ThreadLocalRandom and SplittableRandom are much better, although I still wish for period of 2^128.
But I've never cared about random doubles.
"""how many doubles are in the interval [0, 1)?""" Hmmmm, I thought the answer was 2^53 !
16-05-2017
The blog in question is now available from the internet archive:
http://web.archive.org/web/20141018100950/http://engineering.medallia.com/blog/2014/08/a-plea-for-an-equal-opportunity-random/
Key excerpts:
"If we look again at the above code, we realize that it returns at most 2^53 different values. But, how many doubles are in the interval [0, 1)? The answer is about 2^62. nextDouble() returns just a tiny subset of all the possible double numbers (1 in 500). This small elite of privileged doubles are selected while the vast majority are neglected."
16-05-2017
It would be nice if we could deprecate j.u.Random, otherwise we are stuck updating the docs.
IIUC ThreadLocalRandom and SplittableRandom may also be affected and we might be able to fix those, although i dunno how important this is. The code for SplittableRandom is below:
private static final double DOUBLE_UNIT = 0x1.0p-53; // 1.0 / (1L << 53)
public double nextDouble() {
return (mix64(nextSeed()) >>> 11) * DOUBLE_UNIT;
}
26-08-2014
This particular method and its tight behavioral specification dates back from the very start of Java when "write once, run anywhere" had a particularly strong interpretation. Therefore, I don't think this method should be changed since people have had more than a decade and a half to rely on the details of how it acts. However, subclasses of Random can and should use more sophisticated algorithms.
11-08-2014
Or, we might want to do the right thing this time, and drop the implementation from Javadoc? :)
11-08-2014
Given that Random overly specifies the implementation then it might be best to just clarify the javadoc that results may not be completely uniform.