How Java random generator works?
Check How does java.util.Random work and how good is it?:
In other words, we begin with some start or "seed" number which ideally is "genuinely unpredictable", and which in practice is "unpredictable enough". For example, the number of milliseconds— or even nanoseconds— since the computer was switched on is available on most systems. Then, each time we want a random number, we multiply the current seed by some fixed number, a, add another fixed number, c, then take the result modulo another fixed number, m. The number a is generally large. This method of random number generation goes back pretty much to the dawn of computing1. Pretty much every "casual" random number generator you can think of— from those of scientific calculators to 1980s home computers to currentday C and Visual Basic library functions— uses some variant of the above formula to generate its random numbers.
And also Predicting the next Math.random() in Java
Yes, it is possible to predict what number a random number generator will produce next. I've seen this called cracking, breaking, or attacking the RNG. Searching for any of those terms along with "random number generator" should turn up a lot of results.
Read How We Learned to Cheat at Online Poker: A Study in Software Security for an excellent first-hand account of how a random number generator can be attacked. To summarize, the authors figured out what RNG was being used based on a faulty shuffling algorithm employed by an online poker site. They then figured out the RNG seed by sampling hands that were dealt. Once they had the algorithm and the seed, they knew exactly how the deck would be arranged after later shuffles.
You can also refer this link.
They're pseudorandom numbers, meaning that for general intents and purposes, they're random enough. However they are deterministic and entirely dependent on the seed. The following code will print out the same 10 numbers twice.
Random rnd = new Random(1234);
for(int i = 0;i < 10; i++)
System.out.println(rnd.nextInt(100));
rnd = new Random(1234);
for(int i = 0;i < 10; i++)
System.out.println(rnd.nextInt(100));
If you can choose the seed, you can precalculate the numbers first, then reset the generator with the same seed and you'll know in advance what numbers come out.
I want to know if there is a way to "predict" next generated number and how JVM determines what number to generate next?
Absolutely. The Random
class is implemented as a linear congruential number generator (LCNG). The general formula for a linear congruential generator is:
new_state = (old_state * C1 + C2) modulo N
The precise algorithm used by Random
is specified in the javadocs. If you know the current state of the generator1, the next state is completely predictable.
Will my code output numbers close to real random at any JVM and OS?
If you use Random
, then No. Not for any JVM on any OS.
The sequence produced by an LCNG is definitely not random, and has statistical properties that are significantly different from a true random sequence. (The sequence will be strongly auto-correlated, and this will show up if you plot the results of successive calls to Random.nextInt()
.)
Is this a problem? Well it depends on what your application needs. If you need "random" numbers that are hard to predict (e.g. for an algorithm that is security related), then clearly no. And if the numbers are going to be used for a Monte Carlo simulation, then the inate auto-correlation of a LCNG can distort the simulation. But if you are just building a solitaire card game ... it maybe doesn't matter.
1 - To be clear, the state of a Random
object consists of the values of its instance variables; see the source code. You can examine them using a debugger. At a pinch you could access them and even update them using Java reflection, but I would not advise doing that. The "previous" state is not recorded.