When using class java.util.Random, how can one get the value obtained from calling the method nextInt() N times, but in a much more efficient way (in O(1) specifically)?
For example, if I construct a Random object with a particular seed value, and I want to get the 100,000th “nextInt() value” (that is, the value obtained after calling the method nextInt() 100,000 times) in a fast way, could I do it?
Assume, for simplicity, version 1.7.06 of the JDK, since it may be required to know the exact values of some private fields in class Random. And speaking of, I found the following fields to be relevant in the calculation of a random value:
private static final long multiplier = 0x5DEECE66DL;
private static final long addend = 0xBL;
private static final long mask = (1L << 48) - 1;
After exploring a bit about randomness, I found that random values are obtained using a Linear congruential generator. The actual method that executes the algorithm is method next(int):
protected int next(int bits) {
long oldseed, nextseed;
AtomicLong seed = this.seed;
do {
oldseed = seed.get();
nextseed = (oldseed * multiplier + addend) & mask;
} while (!seed.compareAndSet(oldseed, nextseed));
return (int)(nextseed >>> (48 - bits));
}
The relevant line for the algorithm is the one that obtains the next seed value:
nextseed = (oldseed * multiplier + addend) & mask;
So, to be more specific, is there a way that I can generalize this formula to obtain the “nth nextseed” value? I’m assuming here that after having that, I can then simply obtain the nth int value by letting the variable “bits” be 32 (the method nextInt() simply calls next(32) and returns the result).
Thanks in advance
PS: Perhaps this is a question more suitable for mathexchange?
You can do it in
O(log N)time. Starting withs(0), if we ignore the modulus (248) for the moment, we can see (usingmandaas shorthand formultiplierandaddend) thatNow,
m^N (mod 2^48)can easily be computed inO(log N)steps by modular exponentiation by repeated squaring.The other part is a bit more complicated. Ignoring the modulus again for the moment, the geometric sum is
What makes computing this modulo
2^48a bit nontrivial is thatm - 1is not coprime to the modulus. However, sincethe greatest common divisor of
m-1and the modulus is 4, and(m-1)/4has a modular inverseinvmodulo2^48. LetThen
So
M ≡ m^N (mod 2^50)invto obtain