Hello.
1) extending Random Doug Lea wrote: >Q: Why isn't SplittableRandom a subclass of Random? >A: Class Random requires thread-safety in its spec. It would be >nonsensical for SplittableRandom to comply. Random Javadoc states "Instances of java.util.Random are threadsafe." but ThreadLocalRandom extends Random and is not, so why not consider that the thread-safety statement only applies to Random.class, and not to Random subclasses? 2) third alternative Doug Lea wrote: >If you want to create a stream of random numbers to drive a parallel >computation, you'd choose among two options, neither of them providing >what you probably want: (1) Use a stream based on a single shared >java.util.Random object, in which case your program will encounter >stunning slowdowns when run with many cores; or (2) Use a stream based >on ThreadLocalRandom, What I would have used (maybe because I'm not an expert!) is something like this: new Subtask(new MySequentialRandom(currentTaskRandom.nextLong())).fork() with nextLong() returning something else than current seed of course, to avoid ending up with the same sequence of pseudo-random numbers. In what way would new Subtask(aSplittableRandom.split()).fork() be better than that? The Javadoc for split() says that the values of the returned object should have the same (i.e. as good?) statistical properties, but wouldn't it also be the case with a good non-thread-safe Random, like based on MersenneTwister, which could be seeded with multiple longs? 3) nextDouble() With this method: public double nextDouble() { long bits = (1023L << 52) | (nextLong() >>> 12); return Double.longBitsToDouble(bits) - 1.0; } the returned value granularity is only 1/2^52, i.e. last mantissa bit is always zero. For example the highest value you can return is 1.9999999999999998 - 1.0 i.e. 0.9999999999999998 and so 0.9999999999999999 is never returned. One could use that instead, which doesn't have that problem, and provides values in [0,1-1/2^53], with 1/2^53 granularity: public double nextDouble() { return (this.nextLong() & ((1L<<53)-1)) * (1.0/(1L<<53)); } but it can be a bit slower (maybe due to cast of huge longs into double being slow on some architectures). If needing speed over accuracy, one can replace nextLong() with nextInt(), mask with Integer.MAX_VALUE, and 53 with 31. 4) nextGaussian() Currently there is no nextGaussian(): if added, would it use Random/TLR's algorithm, or some variation of the Ziggurat method (which can be about four times faster)? -Jeff