Generating Random Numbers

Naveen AnamaneniUpdated · 4 min read

A ludo game rolls a die. A quiz app shuffles its questions. A bank sends a one-time password (OTP). All of them need random numbers, but not all random numbers are equal: a dice game just needs variety, while an OTP must be impossible to guess. Java offers a tool for each job, and choosing the right one matters.

Four Tools

ToolUse forExample
Math.random()Quick experimentsa double from 0.0 (inclusive) to 1.0 (exclusive)
java.util.RandomGames, simulations, repeatable tests with a seednew Random(42).nextInt(1, 7)
ThreadLocalRandomEveryday ranges, fast, safe with many threadsThreadLocalRandom.current().nextInt(1, 7)
java.security.SecureRandomOTPs, passwords, tokens: anything secretnew SecureRandom().nextInt(1_000_000)

Rolling a Die

Dice.java▶ Try it
import java.util.concurrent.ThreadLocalRandom;
 
public class Dice {
    public static void main(String[] args) {
        int die = ThreadLocalRandom.current().nextInt(1, 7);
        double chance = Math.random();
        System.out.println("You rolled " + die);
        System.out.printf("Random fraction: %.3f%n", chance);
    }
}
Output
You rolled 4
Random fraction: 0.712

The output changes on every run; that's the point. Math.random() gives a double in [0.0, 1.0). To turn it into a range, the classic formula is (int) (Math.random() * 6) + 1 for 1 to 6, but nextInt(1, 7) says the same thing more clearly.

Repeatable Randomness with a Seed

A Random created with a seed produces the same sequence every time. That sounds odd, but it's exactly what tests and simulations need:

Seeded.java▶ Try it
import java.util.Random;
 
public class Seeded {
    public static void main(String[] args) {
        Random dice = new Random(42);
        for (int i = 0; i < 5; i++) {
            System.out.print(dice.nextInt(1, 7) + " ");
        }
        System.out.println();
    }
}
Output
3 4 1 3 1

How it works

  1. Line 5 creates a generator with seed 42.
  2. Line 7 rolls five dice. Run it again, on any computer, and you get 3 4 1 3 1 again.
  3. Without a seed (new Random()), the sequence is different each run.

Try it yourself: change the seed to 7. Does the sequence change? Does it stay the same across runs?

A Six-Digit OTP

Otp.java▶ Try it
import java.security.SecureRandom;
 
public class Otp {
    public static void main(String[] args) {
        SecureRandom secure = new SecureRandom();
        int otp = secure.nextInt(1_000_000);
        System.out.printf("Your OTP is %06d%n", otp);
    }
}
Output
Your OTP is 048213

nextInt(1_000_000) gives 0 to 999,999, and %06d pads it to six digits with leading zeros, so 48213 prints as 048213.

Common Mistakes

Off-by-one ranges. nextInt(1, 6) never returns 6. The upper bound is exclusive.

Creating a new Random inside a loop. It's wasteful; create one and reuse it, or use ThreadLocalRandom.current().

Using a fixed seed in production. Seeds are for tests. A game with new Random(42) deals the same cards every time.

Practice

  1. Easy: Simulate tossing a coin 10 times and count heads and tails.
  2. Harder: Shuffle an array of five names (Navika, Srihitha, Advitha and two more) using the Fisher-Yates method: for i from the end down to 1, swap element i with a random element from 0 to i.

Quick check: Random numbers

4 questions
1What range does nextInt(1, 7) return?
2What does Math.random() return?
3Which should generate an OTP?
4What happens when two Random objects use the same seed?

Key Takeaways

Was this tutorial helpful?

Lesson 90 of 482