Skip to main content

Section 3.5 The Random Class

Another useful class provided by the JDK is Random. This class gives you the ability to generate pseudorandom numbers. The Random class is a great example of encapsulation in object oriented programming. Performing high quality pseudorandom number generation can be tricky. I should not need to implement an algorithm when high quality an thoroughly debugged algorithms exist already. I can understand what the algorithm produces without knowing the specific details for how the algorithm works. The Random class encapsulates these algorithms and exposes them as simple methods. Letโ€™s explore a bit more of what Random can do.

Subsection 3.5.1 Instantiating a Random Object

Pseudorandom numbers are just that โ€” not truly random, but rather an approximation of true randomness. While they appear random, that are generated in a well-defined order using a deterministic algorithm. A sequence of pseudorandom numbers is repeated when it starts at the same seed value, which has type long. A Random object may be instantiated with a seed as the parameter, or with no parameters at all. If no seed is specified in the Random constructor, then one is selected for you, usually derived from current value of the running JVMโ€™s high-resolution time source.
Like Scanner, the Random class is not available automatically in java. It must first be imported from java.util.Random. A Random object is instantiated using the new keyword and the standard constructor syntax. Once instantiated, the Random object can be used repeatedly to generate various types of random numbers.
Random rnd1 = new Random(123L);   // Create Random object with seed 123L
Random rnd2 = new Random();       // Create Random object with automatic seed
Listing 3.5.1. Random constructor examples.

Subsection 3.5.2 Random Methods

Random object methods give us the ability to generate a variety of different random number types, selected from uniform and normal (Gaussian) distributions. The following table describes many of these methods.
Table 3.5.2. Several Random Methods
Method Returns Description
nextInt(int max) int Compute a uniformly distributed
pseudorandom int in [0, max).
Inclusive of 0 but exclusive of max.
nextDouble() double Compute a uniformly distributed
pseudorandom double in [0.0, 1.0).
nextBoolean() boolean Compute an equally distributed
pseudorandom boolean in {true, false}.
nextGaussian() double Compute a normally distributed
pseudorandom double with mean 0.0
and standard deviation 1.0
setSeed(long seed) void Reset the seed of the pseudorandom
number generator.

Subsection 3.5.3 Random Example

In the following example program we create a Random object and assign it to the variable rnd. Then we use the object to test the nextInt(โ€ฆ), nextDouble(), and nextGaussian() methods.
nextInt(โ€ฆ)intexclusiveinclusivernd.nextInt(10)
// RandomExample.java 
import java.util.Random;

public class RandomExample {
    public static void main(String[] args) {
        int i1, i2;
        double x1, x2, x3;

        Random rnd = new Random();
        
        // Pseudorandom ints in range [0, 10)
        // The value 10, is out of range
        i1 = rnd.nextInt(10);
        i2 = rnd.nextInt(10);
        System.out.println(i1 + ", " + i2);

        // Pseudorandom doubles in range [0.0, 1.0)
        x1 = rnd.nextDouble();
        x2 = rnd.nextDouble();
        System.out.println(x1 + ", " + x2);

        // Pseudorandom double with mean 0.0 
        // and standard deviation 1.0
        x1 = rnd.nextGaussian();
        x2 = rnd.nextGaussian();
        x3 = rnd.nextGaussian();
        System.out.println(x1 + ", " + x2 + ", " + x3);
    }
}
Listing 3.5.3. Random method examples.
javac RandomExample.java
java RandomExample
3, 2
0.46419492484058866, 0.7672336564431435
-0.539505561690596, 0.3820743615836469, 1.5448345622446626
java RandomExample
8, 4
0.4287714292408068, 0.8200307030697347
0.39003589589258647, 0.609691139278949, -0.3421636964155645
java RandomExample
9, 0
0.06465674365837526, 0.6659245501706238
0.6516158074847989, -0.678154539495678, -0.7702039482811629
While the Random object methods give us the basis for generating pseudorandom numbers, practical applications will require us to modify the range within which the numbers are generated to suit our application requirements. Specifically, weโ€™ll often need to scale random number ranges to make them wider or more narrow, and weโ€™ll often have to translate (shift) ranges to higher and lower values. It is fortunate that the pseudorandom number generator methods include 0 at one end of the range of generated numbers. As youโ€™ll see, this is convenient when manipulating these numeric ranges.
The easist way to scale and translate pseudorandom number ranges is to operate on their lower and higher bounds separately. If we modify the bounds correctly, the inner values of the range will follow. We can easily modify the width of a range by multiplying values generated by a suitable scale factor. For example, if we are interested in a pseudorandom double in the range [0.0, 2.0) we would multiply values returned from nextDouble() by 2.0, as follows. We know that the newly generated values will fall in the range [0.0, 2.0).
Table 3.5.4.
2.0ร—[0.0,1.0)
[2.0ร—0.0,2.0ร—1.0)
[0.0,2.0)
Similarly, we can add a constant to a range to translate it to a new location.
Consider the following examples. In all cases assume rnd is a previously instantiated Random object.

Activity 3.5.1.

Write a Java expression that returns a uniformly distributed double in the range [-1.0, 1.0).
Hint.
First multiply the range by a suitable scale factor, then shift by subtracting a suitable constant.
Answer.
2.0 * rnd.nextDouble() - 1.0

Activity 3.5.2.

Write a Java expression that returns a uniformly distributed int in the range [1, 10].
Hint.
Watch out for the upper bound; it is inclusive of 10. Also note that the range includes 10 integers, and is shifted by 1.
Answer.
rnd.nextInt(10) + 1

Activity 3.5.3.

Write a Java expression that returns a uniformly distributed int in the range [-10, -5].
Hint.
Watch out for the lower bound; it is inclusive of -10. The range includes 6 integers and is shifted. Multiplying by a negative number causes the bounds of a range to swap roles.
Answer.
rnd.nextInt(6) - 10 or -5 - rnd.nextInt(6)

Activity 3.5.4.

Write a Java expression that returns a normally distributed double with mean 5.0 and standard deviation of 2.0.
Hint.
Multiply to scale range to width of standard deviation and add a constant to translate to mean.
Answer.
rnd.nextGaussian()*2.0 + 5.0