I want to generate random numbers in java, I know I should use existing methods like Math.random(), however, my question is: how can I generate the same sequence of numbers,
An example of using the same seed repeatedly.
public static void main(String... args) throws IOException {
printDoublesForSeed(1);
printDoublesForSeed(128);
printDoublesForSeed(1);
printDoublesForSeed(128);
}
private static void printDoublesForSeed(long seed) {
double[] doubles = new double[10];
Random rand = new Random(seed);
for (int j = 0; j < doubles.length; j++) {
doubles[j] = (long) (rand.nextDouble() * 100) / 100.0;
}
System.out.println("doubles with seed " + seed + " " + Arrays.toString(doubles));
}
prints
doubles with seed 1 [0.73, 0.41, 0.2, 0.33, 0.96, 0.0, 0.96, 0.93, 0.94, 0.93]
doubles with seed 128 [0.74, 0.53, 0.63, 0.41, 0.21, 0.2, 0.33, 0.74, 0.17, 0.47]
doubles with seed 1 [0.73, 0.41, 0.2, 0.33, 0.96, 0.0, 0.96, 0.93, 0.94, 0.93]
doubles with seed 128 [0.74, 0.53, 0.63, 0.41, 0.21, 0.2, 0.33, 0.74, 0.17, 0.47]
EDIT An interesting abuse of random seeds.
public static void main(String ... args) {
System.out.println(randomString(-6225973)+' '+randomString(1598025));
}
public static String randomString(int seed) {
Random rand = new Random(seed);
StringBuilder sb = new StringBuilder();
for(int i=0;i<5;i++)
sb.append((char) ('a' + rand.nextInt(26)));
return sb.toString();
}
prints
hello world
Math.random
is just a wrapper of the class java.util.Random
. The first time you call Math.random
an instance of the class java.util.Random
is created.
Now, most API's don't expose any true random number generators, because they cannot be implemented in software. Instead, they use pseudo-random number generators, which generate a sequence of random-looking numbers using a bunch of formulas. This is what java.util.Random
does. However, every pseudo-random number generator needs to be seeded first. If you have two pseudo-random number generators which use the same algorithm and use the same seed, they will produce the same output.
By default, java.util.Random
uses the milliseconds since January 1, 1970 as the seed. Therefore, everytime you start your program, it will produce different numbers (unless you manage it to start java up in under 1 millisecond). So, the solution to your problem is to create your own java.util.Random
instance and seed it by yourself:
import java.util.Random;
class ... {
Random randomNumberGenerator = new Random(199711);
public void ...()
{
int randomInt = randomNumberGenerator.nextInt();
double randomDouble = randomNumberGenerator.nextDouble();
}
}
The randomNumberGenerator
will always spit out the same sequence of numbers, as long as you don't change the seed(the 199711
).
Sure - just create an instance of Random instead of using Math.random()
, and always specify the same seed:
Random random = new Random(10000); // Or whatever seed - maybe configurable
int diceRoll = random.nextInt(6) + 1; // etc
Note that it becomes harder if your application has multiple threads involved, as the timing becomes less predictable.
This takes advantage of Random
being a pseudo-random number generator - in other words, each time you ask it for a new result, it manipulates internal state to give you a random-looking sequence, but knowing the seed (or indeed the current internal state) it's entirely predictable.
You need to seed the random number generator.
Random random = new Random(aFixedNumber);
random.nextInt(); // will always be the same
I'd hardcode the numbers into the app. This takes more memory but is much faster.
Just print random numbers to the terminal, then copy-paste them to your code.
Be sure to leave a comment explaining what you have done, or they will look like black magic to the uninformed reader.