public class XorShift64StarRandom extends Random
More details about xorshift* generators can be found in my paper “An experimental exploration of Marsaglia's xorshift generators,
scrambled”, 2014.
Note that this is not a cryptographic-strength
pseudorandom number generator, but its quality is preposterously higher than Random's
(and its period is 264 − 1).
On an Intel® Core™ i7-4770 CPU @3.40GHz (Haswell),
all methods of this class and of XorShift128PlusRandom except for nextInt() are faster than
those of ThreadLocalRandom (available only from Java 7).
Timings are orders of magnitude faster than Random's, but Random is slowed down by the
fact of being thread safe, so the comparison is not fair.
The following table reports timings
in nanoseconds for some type of calls for ThreadLocalRandom,
for XorShift128PlusRandom (the fastest), for this class, for XorShift1024StarRandom and for the xorgens generator
described by Richard P. Brent in “Some long-period random number generators using shifts and xors”, ANZIAM Journal 48 (CTAC2006), C188-C202, 2007:
ThreadLocalRandom
| XorShift128PlusRandom
| XorShift64StarRandom
| XorShift1024StarRandom
| xorgens | |
|---|---|---|---|---|---|
| nextInt() | 1.33 | 1.42 | 1.70 | 2.16 | 2.57 |
| nextLong() | 2.72 | 1.29 | 1.62 | 2.06 | 2.32 |
| nextDouble() | 2.81 | 2.06 | 2.06 | 2.13 | 2.58 |
| nextInt(1000000) | 2.89 | 2.74 | 2.33 | 3.25 | 3.75 |
| nextInt(2^29+2^28) | 6.47 | 2.85 | 2.40 | 3.49 | 4.02 |
| nextInt(2^30) | 2.86 | 2.34 | 1.80 | 2.68 | 2.91 |
| nextInt(2^30+1) | 12.12 | 2.82 | 2.27 | 3.38 | 3.98 |
| nextInt(2^30+2^29) | 6.37 | 2.85 | 2.40 | 3.49 | 4.02 |
| nextLong(1000000000000) | 72.55 | 2.59 | 3.01 | 3.18 | 3.94 |
| nextLong(2^62+1) | 229.04 | 12.59 | 13.14 | 15.06 | 16.01 |
Note that the relative differences between generators are actually more marked than these figures show, as the timings include the execution of a loop and of a xor instruction that combines the results to avoid excision.
The quality of this generator is high: for instance, it performs better than WELL1024a
or MT19937 in the TestU01 BigCrush suite.
More details can be found on the xorshift*/xorshift+ generators and the PRNG shootout page.
This class extends Random, overriding (as usual) the Random.next(int) method. Nonetheless,
since the generator is inherently 64-bit also Random.nextInt(), Random.nextInt(int),
Random.nextLong() and Random.nextDouble() have been overridden for speed (preserving, of course, Random's semantics).
See in particular the comments in the documentation of nextInt(int), which is tailored for speed at the price of an essentially undetectable bias.
If you do not need an instance of Random, or if you need a RandomGenerator to use
with Commons Math, you might be wanting
XorShift64StarRandomGenerator instead of this class.
If you need a longer period, consider using XorShift1024StarRandom or XorShift1024StarRandomGenerator.
The lower bits of this generator are of slightly better quality than the higher bits. Thus, masking the lower bits is a safe and effective way to obtain small random numbers. The code in this class usually extracts lower bits, rather than upper bits, whenever a subset of bits is necessary (when extracting 63 bits we use a right shift for performance reasons, though).
| Constructor and Description |
|---|
XorShift64StarRandom()
Creates a new generator seeded using
Util.randomSeed(). |
XorShift64StarRandom(long seed)
Creates a new generator using a given seed.
|
| Modifier and Type | Method and Description |
|---|---|
protected int |
next(int bits) |
boolean |
nextBoolean() |
void |
nextBytes(byte[] bytes) |
double |
nextDouble() |
float |
nextFloat() |
int |
nextInt() |
int |
nextInt(int n)
Returns a pseudorandom, approximately uniformly distributed
int value
between 0 (inclusive) and the specified value (exclusive), drawn from
this random number generator's sequence. |
long |
nextLong() |
long |
nextLong(long n)
Returns a pseudorandom uniformly distributed
long value
between 0 (inclusive) and the specified value (exclusive), drawn from
this random number generator's sequence. |
void |
setSeed(long seed)
Sets the seed of this generator.
|
void |
setState(long state)
Sets the state of this generator.
|
nextGaussianpublic XorShift64StarRandom()
Util.randomSeed().public XorShift64StarRandom(long seed)
seed - a nonzero seed for the generator (if zero, the generator will be seeded with -1).public int nextInt(int n)
int value
between 0 (inclusive) and the specified value (exclusive), drawn from
this random number generator's sequence.
The hedge “approximately” is due to the fact that to be always
faster than ThreadLocalRandom
we return
the upper 63 bits of nextLong() modulo n instead of using
Random's fancy algorithm (which nextLong(long) uses though).
This choice introduces a bias: the numbers from 0 to 263 mod n
are slightly more likely than the other ones. In the worst case, “more likely”
means 1.00000000023 times more likely, which is in practice undetectable (actually,
due to the abysmally low quality of Random's generator, the result is statistically
better in any case than Random.nextInt(int)'s) .
If for some reason you need truly uniform generation, just use nextLong(long).
public long nextLong(long n)
long value
between 0 (inclusive) and the specified value (exclusive), drawn from
this random number generator's sequence. The algorithm used to generate
the value guarantees that the result is uniform, provided that the
sequence of 64-bit values produced by this generator is.n - the positive bound on the random number to be returned.long value between 0 (inclusive) and n (exclusive).public double nextDouble()
nextDouble in class Randompublic boolean nextBoolean()
nextBoolean in class Randompublic void setSeed(long seed)
The seed will be passed through HashCommon.murmurHash3(long). In this way, if the
user passes a small value we will avoid the short irregular transient associated
with states with a very small number of bits set.
setSeed in class Randomseed - a nonzero seed for this generator (if zero, the generator will be seeded with Long.MIN_VALUE).public void setState(long state)
state - the new state for this generator (must be nonzero).