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, each time I run my application? example: the generated sequence is: 0.9, 0.08,0.6 so I want that this sequence will be generated every time I execute this method..
5 Answers
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.
1 Comment
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
1 Comment
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).