Question

Generate Random Integers in a Range in Java

javarandominteger

Question

How can I generate a random int value within a specific range in Java?

The following approaches have problems related to correctness and integer overflow:

randomNum = minimum + (int)(Math.random() * maximum);

This is incorrect because randomNum can become larger than maximum.

Random rn = new Random();
int n = maximum - minimum + 1;
int i = rn.nextInt() % n;
randomNum = minimum + i;

This is also incorrect because randomNum can become smaller than minimum.

What is the correct way to generate a random integer between minimum and maximum in Java?

Short Answer

By the end of this page, you will understand how to generate random integers in Java safely and correctly for both inclusive and exclusive ranges. You will also learn why some common formulas fail, how Random.nextInt(bound) works, and when to use Random, ThreadLocalRandom, or Math.random().

Concept

Generating a random integer in a range means producing a whole number between two limits, such as from 5 to 10.

The key idea is:

  1. Find the size of the range
  2. Generate a random offset inside that range
  3. Shift that offset by the minimum value

For example, if the range is 5 to 10 inclusive, the possible values are:

  • 5
  • 6
  • 7
  • 8
  • 9
  • 10

That is 6 values total, so the range size is:

maximum - minimum + 1

Then you generate a random number from 0 up to rangeSize - 1, and add minimum.

In Java, the safest standard approach is usually:

int randomNum = minimum + random.nextInt(maximum - minimum + 1);

This works because nextInt(bound) returns a value from 0 inclusive to bound exclusive.

So if bound is 6, the result is one of:

  • 0
  • 1
  • 2
  • 3
  • 4
  • 5

Adding minimum shifts that to the desired range.

This matters in real programming because random values are used everywhere:

  • game logic
  • simulations
  • test data generation
  • sampling
  • temporary codes
  • choosing random items from collections

If the formula is wrong, your program may:

  • generate values outside the expected range
  • skip some values
  • bias the distribution
  • fail near integer limits

So this is not just about syntax. It is about correctness and reliability.

Mental Model

Think of a random number in a range like picking a seat number in a row.

If seats go from 20 to 25, you do not directly guess a number from the whole world of integers. Instead:

  1. Count how many seats exist
  2. Pick a random position starting from 0
  3. Move that many seats forward from seat 20

So:

  • seat range: 20 to 25
  • total seats: 6
  • random offset: 0 to 5
  • final seat: 20 + offset

That is exactly how random integer range formulas work.

The mistake beginners often make is mixing up:

  • the largest allowed value
  • the size of the range

These are not the same thing.

Take Quiz

Syntax and Examples

Basic inclusive range with Random

import java.util.Random;

Random random = new Random();
int minimum = 5;
int maximum = 10;

int randomNum = minimum + random.nextInt(maximum - minimum + 1);
System.out.println(randomNum);

This returns a value from 5 to 10, including both ends.

Why this works

random.nextInt(maximum - minimum + 1)

If minimum = 5 and maximum = 10, then:

maximum - minimum + 1 = 6

So nextInt(6) returns one of:

0, 1, 2, 3, 4, 5

Then adding minimum gives:

5, 6, 7, 8, 9, 10

Using ThreadLocalRandom in modern Java

import java.util.concurrent.ThreadLocalRandom;

int minimum = 5;
int maximum = 10;

int randomNum = ThreadLocalRandom.current().nextInt(minimum, maximum + 1);
System.out.println(randomNum);

This is often cleaner. The second argument is exclusive, so maximum + 1 makes the upper limit inclusive.

Exclusive upper bound example

If you want values from 5 up to but not including 10:

int randomNum = ThreadLocalRandom.current().nextInt(5, 10);

Possible values are:

  • 5
  • 6
  • 7
  • 8
  • 9

Using Math.random() correctly

int minimum = 5;
int maximum = 10;

int randomNum = minimum + (int)(Math.random() * (maximum - minimum + 1));
System.out.println(randomNum);

This can work, but Random or ThreadLocalRandom is usually clearer and preferred in real code.

Important validation

Always ensure:

minimum <= maximum

For example:

if (minimum > maximum) {
    throw new IllegalArgumentException("minimum must be <= maximum");
}

Step by Step Execution

Consider this code:

import java.util.Random;

public class Main {
    public static void main(String[] args) {
        Random random = new Random();
        int minimum = 3;
        int maximum = 7;

        int result = minimum + random.nextInt(maximum - minimum + 1);
        System.out.println(result);
    }
}

Step 1: Calculate the range size

maximum - minimum + 1

Substitute values:

7 - 3 + 1 = 5

So we need a random number from a set of 5 possible offsets.

Step 2: Generate the offset

random.nextInt(5)

This may return any of:

0, 1, 2, 3, 4

Suppose it returns 2.

Step 3: Shift by the minimum

result = 3 + 2;

So:

result = 5

Step 4: Check the possible outcomes

If the offset is:

  • 0 → result is 3
  • 1 → result is 4
  • 2 → result is 5
  • 3 → result is 6
  • 4 → result is 7

That exactly matches the desired inclusive range.

Why the broken % n version fails

int i = rn.nextInt() % n;

rn.nextInt() may be negative. In Java, % keeps the sign of the left operand, so i can be negative.

Example:

rn.nextInt() = -8
n = 5
-8 % 5 = -3

Then:

randomNum = minimum + (-3)

This can go below minimum.

Why the Math.random() * maximum version fails

minimum + (int)(Math.random() * maximum)

This uses maximum as if it were the range size, but it is not.

If:

  • minimum = 5
  • maximum = 10

Then (int)(Math.random() * 10) can be from 0 to 9, and adding 5 gives 5 to 14.

That clearly exceeds maximum.

Real World Use Cases

Picking a random item ID for testing

When generating sample user IDs, order numbers, or ticket numbers, you often need a random integer in a valid numeric range.

Game development

Games use random ranges for:

  • dice rolls
  • enemy damage
  • loot drops
  • random spawn coordinates

Example:

int damage = ThreadLocalRandom.current().nextInt(10, 21);

This produces damage from 10 to 20 inclusive.

Simulations

In simulations such as queues, traffic, or load testing, random integers help model variable behavior.

Picking a random array index

String[] names = {"Ana", "Ben", "Cara"};
int index = ThreadLocalRandom.current().nextInt(0, names.length);
System.out.println(names[index]);

This is one of the most common real uses of ranged random integers.

Temporary codes or tokens

For simple non-secure uses such as demo verification codes:

int code = ThreadLocalRandom.current().nextInt(100000, 1000000);

This produces a 6-digit number.

For real security-sensitive tokens, use SecureRandom instead.

Take Quiz

Real Codebase Usage

In real projects, developers usually wrap random range logic in a helper method instead of repeating formulas everywhere.

Helper method pattern

import java.util.concurrent.ThreadLocalRandom;

public static int randomInRange(int min, int max) {
    if (min > max) {
        throw new IllegalArgumentException("min must be <= max");
    }
    return ThreadLocalRandom.current().nextInt(min, max + 1);
}

This improves readability and reduces mistakes.

Guard clause for validation

A common pattern is checking inputs early:

if (min > max) {
    throw new IllegalArgumentException("Invalid range");
}

This prevents hidden bugs later.

Configuration-driven ranges

Applications often read limits from config files or environment variables:

int minRetries = 1;
int maxRetries = 3;
int retryDelay = ThreadLocalRandom.current().nextInt(minRetries, maxRetries + 1);

Test data generation

Developers often create random but valid values for automated tests:

int age = ThreadLocalRandom.current().nextInt(18, 66);

Error handling and boundary safety

When ranges might be near integer limits, developers are careful with max + 1 because it can overflow if max == Integer.MAX_VALUE.

In such cases, use a different strategy or a wider type like long when appropriate.

Multi-threaded applications

In concurrent code, ThreadLocalRandom is commonly preferred over sharing a single Random instance because it performs better and is designed for threaded use.

Common Mistakes

1. Using maximum instead of range size

Broken code:

int randomNum = minimum + (int)(Math.random() * maximum);

Why it is wrong:

  • maximum is the upper value, not the number of possible values
  • this can create numbers above the allowed maximum

Correct version:

int randomNum = minimum + (int)(Math.random() * (maximum - minimum + 1));

2. Using % to limit random numbers

Broken code:

int i = random.nextInt() % n;

Why it is wrong:

  • results can be negative
  • distribution may be uneven

Correct version:

int i = random.nextInt(n);

3. Forgetting whether the upper bound is inclusive or exclusive

nextInt(bound) means:

  • lower bound is 0 inclusive
  • upper bound is bound exclusive

So:

random.nextInt(5)

returns 0 to 4, not 0 to 5.

4. Not validating min and max

Broken code:

int result = min + random.nextInt(max - min + 1);

If min > max, this fails.

Safer code:

if (min > max) {
    throw new IllegalArgumentException("min must be <= max");
}

5. Ignoring overflow near integer limits

This can be dangerous:

ThreadLocalRandom.current().nextInt(min, max + 1);

If max is Integer.MAX_VALUE, then max + 1 overflows.

6. Using random APIs for security-sensitive tasks

For passwords, reset tokens, or secure codes, do not use Random or Math.random().

Use:

import java.security.SecureRandom;

Comparisons

ApproachExampleRange StyleGood Choice?Notes
Math.random()min + (int)(Math.random() * (max - min + 1))Inclusive with manual formulaSometimesWorks, but less explicit
Random.nextInt(bound)min + random.nextInt(max - min + 1)Inclusive with manual shiftYesClassic and common
ThreadLocalRandom.nextInt(min, maxExclusive)ThreadLocalRandom.current().nextInt(min, max + 1)Upper bound exclusiveYesVery convenient, common in modern Java
SecureRandommin + secureRandom.nextInt(max - min + 1)Inclusive with manual shiftYes, for securitySlower but appropriate for secure values

Random vs ThreadLocalRandom

FeatureRandomThreadLocalRandom
Easy to useYesYes
Good for single-threaded codeYesYes
Better in multi-threaded codeNoYes
Need to create an instanceYesNo
Direct ranged method with origin and boundNoYes

Inclusive vs exclusive upper bound

FormulaResult
random.nextInt(5)0 to 4
min + random.nextInt(max - min + 1)min to max
ThreadLocalRandom.current().nextInt(min, max)min to max - 1
ThreadLocalRandom.current().nextInt(min, max + 1)min to max
Take Quiz

Cheat Sheet

// Inclusive range: [min, max]
int value = min + random.nextInt(max - min + 1);

// Inclusive range with ThreadLocalRandom
int value = ThreadLocalRandom.current().nextInt(min, max + 1);

// Exclusive upper bound: [min, max)
int value = ThreadLocalRandom.current().nextInt(min, max);

// Math.random() version for inclusive range
int value = min + (int)(Math.random() * (max - min + 1));

Rules to remember

  • nextInt(bound) returns 0 to bound - 1
  • To include max, use max - min + 1
  • Do not use % to force a random value into a range
  • Validate that min <= max
  • Watch out for overflow when using max + 1
  • Use SecureRandom for security-sensitive values

Safe helper

public static int randomInRange(int min, int max) {
    if (min > max) {
        throw new IllegalArgumentException("min must be <= max");
    }
    return min + new Random().nextInt(max - min + 1);
}

Edge case

If max == Integer.MAX_VALUE, then:

max + 1

overflows for int. Be careful with inclusive formulas that add 1 to the maximum.

FAQ

How do I generate a random integer between two numbers in Java?

Use:

int value = min + random.nextInt(max - min + 1);

This gives a value from min to max inclusive.

Why does random.nextInt() % n give wrong results?

Because random.nextInt() can be negative, and % n can also be negative. It can also produce uneven distribution.

Is Math.random() okay for generating random integers?

Yes, if used correctly with the proper range formula. But Random or ThreadLocalRandom is usually clearer.

What is the easiest modern Java way to generate a number in a range?

ThreadLocalRandom.current().nextInt(min, max + 1)

This is very readable for inclusive ranges.

Is the upper bound included in nextInt(bound)?

No. The upper bound is exclusive.

random.nextInt(5)

returns 0 to 4.

What should I use for secure random numbers in Java?

Use SecureRandom for passwords, tokens, session secrets, or verification codes that must be hard to guess.

What happens if min is greater than max?

Your code should reject that input, usually by throwing IllegalArgumentException.

Can max + 1 overflow in Java?

Yes. If max is Integer.MAX_VALUE, adding 1 overflows for int. That edge case needs special handling.

Take Quiz

Mini Project

Description

Build a small Java program that simulates rolling a custom die. The user chooses a minimum and maximum value, and the program generates a random integer in that inclusive range. This demonstrates correct range calculation, input validation, and repeated random generation.

Goal

Create a reusable method that returns a random integer between min and max inclusive, then use it to print several sample results.

Requirements

[ "Create a method that accepts min and max as parameters.", "Validate that min is less than or equal to max.", "Generate a random integer in the inclusive range.", "Call the method multiple times and print the results.", "Use standard Java random utilities rather than manual modulo logic." ]

Take Quiz

Keep learning

Related questions

View more