Java Math.random Examples

Math.Random

1. Introduction

Let us learn how to generate some random numbers in Java. Random numbers are needed for various purposes; maybe you want to generate a password or a session identifier. Whatever the purpose may be, there are a number of issues to be aware of when generating a random number.

2. Using Math.random()

Most common way of generating a random double number in Java is to use Math.random(). Each invocation of this method returns a random number. The following code generates 10 random numbers and prints them.

for (int i = 0 ; i < 10 ; i++) {
    System.out.println(Math.random());
}

This is about as simple as it gets for generating random numbers. Issues with this method include:

  1. There is no way to specify a seed for the generator. It is picked automatically for you.
  2. Math.random() creates an instance of Random for the actual generation. The instance of Random created by this method is synchronized for use with multiple threads. So while this method can safely be used by multiple threads, you might want to employ other methods to reduce contention.

3. Employ the Random class

You could also directly create and use an instance of Random. That way you have more control over the seed, and also generate far more than just random double numbers.

The following code initializes an instance of Random and uses it to generate 10 integers.

Random random = new Random();
for (int i = 0 ; i < 10 ; i++) {
    System.out.println(random.nextInt());
}

4. Specifying the Seed

To specify a particular seed, use the appropriate constructor as follows:

long seed = ...;
Random random = new Random(seed);

Of course, since this is a Pseudo Random Number Generator (PRNG), specifying the same seed results in the same sequence of random numbers being generated. You can verify the fact by specifying a known seed and running the code again.

long seed = Long.parseLong(25);
Random random = new Random(seed);
for (int i = 0 ; i < 10 ; i++) {
    System.out.println(random.nextInt());
}

And that determinism is why when these random numbers are used in secure applications (say generating a password), it is important to “hide” the seed. If someone else were to obtain the same seed, the same sequence can be generated again.

5. Multi-Threaded Applications

While the same instance of Random can be used by different threads (since it is thread-safe), it might be better to use another class more appropriate for the purpose. The ThreadLocalRandom is a direct subclass of Random and does not have the contention problems of a plain Random instance.

Use the instance of ThreadLocalRandom in each thread as follows:

for (int i = 0 ; i < 10 ; i++) {
    System.out.println(ThreadLocalRandom.current().nextInt());
}

The instance of ThreadLocalRandom is initialized with a random seed the first time in each thread. To initialize with a cryptographically secure random seed, set the system property “java.util.secureRandomSeed” to “true“.

6. Cryptographic Security

Some applications require cryptographic level of security in the random number generation. What this means is that the generator must pass tests outlined in section 4.9.1 of this document. You can generate cryptographically secure random numbers using the class SecureRandom.

Implementations of the SecureRandom class might generate pseudo random numbers; this implementation uses a deterministic algorithm (or formula) to produce pseudo random numbers. Some implementations may produce true random numbers while others might use a combination of the two.

Running the following code two times on my machine produced the output shown. Even when the generator is being initialized with a known seed, it produces different sequences. Does that mean the sequence is truly random? The answer lies in how the RNG is initialized. SecureRandom combines the user-specified seed with some random bits from the system. This results in a different sequence even when the seed is set to a known value. Random, on the other hand, just replaces the seed with the user specified value.

byte[] bytes = {'a', 'b', 'c', 'd'};
SecureRandom random = new SecureRandom(bytes);
byte[] output = new byte[10];
random.nextBytes(output);
for (int i = 0 ; i < output.length ; i++) {
    System.out.printf("%#x, ", output[i]);
}
System.out.println();

// prints 1st time: 0xa2, 0x97, 0xd0, 0x43, 0x9, 0x60, 0xc0, 0x56, 0x4c, 0x12,

// prints 2nd time: 0x52, 0x5d, 0x35, 0x11, 0x2, 0x48, 0xe8, 0x46, 0xb8, 0x70,

7. Random Integers in a Specific Range

Generating random integers in a specific range is a frequent requirement. Easiest way to do it:

int value = ThreadLocalRandom.current().nextInt(1, 100);

The above is good for multi-threaded access. However it is not suitable when you need to be able to seed the generator. For that case:

long seed = ...;
Random random = new Random(seed);
int min = 20, max = 150;
int value = random.nextInt(max - min) + min;

Using Math.random():

int value = (int)(Math.random()*(max - min)) + min;

8. Generating a Random Password

What if you want to generate a random string, say for a password or a session identifier? You can use BigInteger as shown below. Use Random when you don’t need cryptographic level security; this will generate a known sequence with a known seed.

long seed = ...;
int radix = 16;
Random random = new Random(seed);
BigInteger bi = new BigInteger(100, random);
System.out.println(bi.toString(radix));

// prints: acc49bbd83fbef2c6f6c00df5

When you need cryptographic security, use SecureRandom.

Random random = new SecureRandom();
BigInteger bi = new BigInteger(100, random);
System.out.println(bi.toString(radix));

// prints: 8a20a626baa846d10068f3581

When you run the above code a second time with the same values of seed (and radix), here is what you get. The string is different with SecureRandom.

// with Random: acc49bbd83fbef2c6f6c00df5
// with SecureRandom: d61c3d3c417c3f613379dda8d

Review

Let’s review.

We learnt how to generate random numbers in Java. Simple methods include using Math.random(). More control is offered by java.util.Random whereas cryptographically secure random numbers can be generated using SecureRandom. For multi-threaded PRNG, we have ThreadLocalRandom class. Finally we learned how to generate random strings using BigInteger.

Leave a Reply

Your email address will not be published. Required fields are marked *