How to generate random numbers in Java

Tuesday, April 15, 2008

Generating random numbers can be useful in many situations. For example, it can be used to determine the value when rolling dice, introduce random movements into character moves in a game, and more.

Note: Technically speaking, when we say “random numbers” here, it actually is pseudo-random numbers, as it is not possible to generate truly random numbers.

There are two common ways to generate random numbers in Java. One method is to make an instance of a java.util.Random class and another is to the use the java.lang.Math.random() method. This how-to will introduce both.

Using the Random class

First method, we can use the java.util.Random class to generate random numbers.

The Random class is quite versatile. There are several methods available which return different types. If you want to produce a random answer for true-false questions, you could use the Random.nextBoolean() method to get a randomly selected boolean. For a full list of the methods available, take a look at the Javadocs for the Random class.

The following is an example of using the Random.nextInt(int) method to simulate rolling dice:

import java.util.Random;

/**
  * RandomApp demonstrates the use of the Random class to generate
  * pseudo-random numbers, simulating a roll of a die.
  * @author coobird
  */
public class RandomApp {
  public static void main(String[] args) {
    // Instantiate a Random object "r"
    Random r = new Random();

    // Random.nextInt(int) returns a value from 0 (inclusive)
    // up to but excluding the int passed into the method.
    // (6 is excluded)
    int number = r.nextInt(6) + 1;

    System.out.println("You rolled a " + number);
  }
}

In the example above, we instantiate a Random object with its default constructor Random(). Then, the Random.nextInt(int) method is called to receive an int to which 1 is added. This is because the Random.nextInt(int) method will return an int from 0 (inclusive) to the int that is passed in, which is excluded. Therefore, calling r.nextInt(6) will actually return random numbers ranging from 0 to 5. Since a die has 1 to 6 as its faces, we need to add a 1 to the returned value to end up with a random number ranging between 1 to 6 to be stored in the variable number.

Seeding Random

The random number generator that the Random class uses is a pseudo-random number generator. It is an algorithm that generates numbers in a specified range with (almost) equal probability for any one value in the range. The details are contained in the Javadoc for the Random class.

When the pseudo-random number generator sets out to generate a number, it requires a parameter called a “seed” to pass to its generator algorithm. When the same value of the seed is given to the algorithm, it will generate pseudo-random numbers, each value with the same probability of being picked from another. However, the sequence at which those values appear will be the same. Since this is usually not desirable when random numbers are wanted, the seed needs to be changed for each time we want to generate random numbers.

One way to seed the pseudo-number generator is to use the current time as the seed for the generator. The System.currentTimeMillis() method returns a long that can be passed to the Random object as its seed. Seeing a Random object can be done when the object is instantiated or through the Random.setSeed(long). Also, calling the Random() constructor will generate a Random object that is seeded with a value that will probably differ on each execution.

Following is an example of seeding the Random object:

import java.util.Random;

/**
* RandomApp2 demonstrates seeding the Random object and how
* that affects the sequence of random numbers that are
* generated.
* @author coobird
  */
public class RandomApp2 {
  private static void rollTheDie(Random r) {
    // Displays the 10 rolls of the die
    System.out.println("Roll the die!");
    for (int i = 0; i < 10; i++)
      System.out.print((r.nextInt(6) + 1) + ", ");
    System.out.println();
  }

  public static void main(String[] args) {
    // Instantiate a Random object, seeded with a value that
    // should vary on each execution
    Random r = new Random();
    // Roll the die.
    rollTheDie(r);
    
    // Now, let's seed the Random object with 42, then
    // roll the die.
    r.setSeed(42);
    rollTheDie(r);
    
    // Now, seed with the current system time and roll.
    r.setSeed(System.currentTimeMillis());
    rollTheDie(r);
  }
}

Rolling the die will generate a sequence of 10 random numbers under three different conditions.

  1. Random object that was instantiated using the default constructor
  2. Random object seeded using setSeed(long) method called with 42 as argument, and
  3. Random object seeded with the current system time.

Running the above program once doesn’t quite tell the whole story. When run three times, I had the following output:

First run:

Roll the die!
2, 5, 3, 6, 6, 2, 4, 3, 1, 3,
Roll the die!
3, 4, 1, 3, 1, 2, 6, 3, 2, 6,
Roll the die!
6, 4, 5, 4, 6, 3, 6, 6, 4, 2,

Second run:

Roll the die!
3, 3, 6, 2, 1, 6, 1, 6, 3, 4,
Roll the die!
3, 4, 1, 3, 1, 2, 6, 3, 2, 6,
Roll the die!
5, 4, 5, 2, 6, 2, 2, 1, 5, 3,

Third run:

Roll the die!
5, 6, 1, 5, 3, 5, 4, 5, 5, 6,
Roll the die!
3, 4, 1, 3, 1, 2, 6, 3, 2, 6,
Roll the die!
5, 1, 2, 6, 6, 3, 3, 2, 1, 3,

If you take a look at the second series of “Roll the die!”, you’ll notice that the sequence of random numbers are exactly the same throughout the three executions. This shows that seeding the Random pseudo-random number generator will generate the same sequence between executions, and the two other methods used did produce different sequences because they used different seeds on each execution.

Note: There are some misconceptions which lead people to seed a random number generator every time a random number is picked. This probably is not necessary, as by seeding the generator once per execution of a program will already generate a new sequence of random numbers.

Another Method

Another method to generate a random number is to use the Math.random() method. The method will return a double with a range of 0.0 to 1.0. This method may be easier to use because it doesn’t require that a Random object is generated and then having to call one of its methods to generate a random number. However, it is limited because it will only return double in the range of 0.0 to 1.0, and by usage, it may require scaling and adjusting the returned value to one’s needs.

The following is the dice program above using the Math.random() method:

/**
 * RandomApp3 demonstrates the use of the Math.random()
 * method to generate pseudo-random numbers, simulating
 * a roll of a die.
 * @author coobird
 */
public class RandomApp3 {
  public static void main(String[] args) {
    // We don't need to make a Random object

    // The Math.random() returns a double between
    // 0.0 and 1.0. In order to get an int between
    // 1 to 6, the double returned must be multiplied
    // by 6, and as before, increased by 1, and
    // finally casted to an int.
    int number = (int)(Math.random() * 6) + 1; 

    System.out.println("You rolled a " + number);
  }
}

As can be seen, a random number can be obtained in just one line, just by calling one method. This may be more convenient if the limitations of the Math.random() does not cause a problem.