Pseudorandom Numbers and Generators

Generate arrays of integers and floating-point values with NumPy's random generator. Treat each result as a sample produced by a deterministic algorithm, specify its shape and range, and inspect the values before using them in a larger computation.

A program sometimes needs values that vary from one draw to another. A simulation may need dice rolls, an experiment may need small artificial noise, and a sampling procedure may need randomly chosen indexes.

A computer follows exact instructions, so NumPy does not obtain these values by making an unexplained choice. It uses a deterministic algorithm that produces a sequence with useful statistical variation. The values are called pseudorandom because an algorithm produces them.

Create a generator

NumPy provides a random number generator: an object that keeps the algorithm's current state and exposes methods for drawing values.

The variable rng refers to the generator. Creating it does not yet draw a number. A method call such as rng.integers(...) or rng.random(...) asks it to produce values and advance to the next state.

Use default_rng for new NumPy code. Older programs may use functions such as np.random.randint, but keeping a generator in a named variable makes the source of randomness explicit and easier to pass into another function.

Draw integers from a half-open interval

The following call draws eight integers:

rolls = rng.integers(1, 7, size=8)

The lower bound 1 is included. The upper bound 7 is excluded. NumPy writes this half-open interval as:

1 <= value < 7

The possible values are therefore 1, 2, 3, 4, 5, 6, which matches an ordinary six-sided die.

The word random does not mean that every small sample must contain every possible value or contain each value equally often. Repeated values are allowed. Eight independent simulated rolls could all happen to be 3; that result would be unusual, but it would still satisfy the requested interval.

When size is omitted, integers returns one NumPy scalar:

one_roll = rng.integers(1, 7)

When size is an integer or shape tuple, the method returns an array with that shape:

Here, ten_rolls.shape is (10,), while roll_grid.shape is (2, 4).

Draw floating-point values

The random method draws floating-point values from a uniform distribution over the interval [0.0, 1.0):

weights = rng.random(5)

The interval means:

0.0 <= value < 1.0

In a uniform distribution, equal-width parts of the interval have equal probability. This is a statement about the process over many draws, not a promise that five values will look evenly spaced.

To move a uniform value into another interval, scale its width and add its lower bound. For a value between -0.2 and 0.2:

noise = -0.2 + rng.random(5) * 0.4

The width is 0.2 - (-0.2) = 0.4. Multiplication changes [0.0, 1.0) to [0.0, 0.4), and adding -0.2 moves it to [-0.2, 0.2).

NumPy also provides methods for other distributions. For example, rng.normal(...) draws values from a normal distribution. This lesson begins with integer and uniform draws because their ranges and shapes are easy to check directly.

Inspect generated values as arrays

Random arrays obey the same rules as other NumPy arrays. They have a shape, number of dimensions, size, and data type. Run the example, then change the shape or interval and inspect the checks.

Generate and inspect two random arrays

The printed checks describe properties guaranteed by the calls. The individual values may change when the generator starts differently.

Ready to run.

The interval checks use elementwise comparisons and np.all. They verify every generated value without requiring one exact array. This distinction matters: the call specifies properties such as range and shape, while the generator selects the individual values.

Distinguish draws from guarantees

For this call:

sample = rng.integers(10, 15, size=(3, 2))

you can know all of the following before running it:

  • sample.shape is (3, 2);
  • sample.size is 6;
  • every value satisfies 10 <= value < 15;
  • the possible values are 10, 11, 12, 13, 14;
  • the result uses an integer data type.

You cannot infer the six exact values unless you also know the generator's initial state and every draw that advanced it before this call.

This gives a useful way to reason about generated data:

method + arguments -> guaranteed properties
generator state -> particular values

The next lesson explains how a seed establishes a repeatable initial state.

Choose the method from the required values

Use rng.integers when the result must contain integers from a bounded half-open interval. Use rng.random when you need floating-point values uniformly distributed over [0.0, 1.0), possibly followed by scaling and shifting.

Before using either result, write down:

  1. the intended value range;
  2. whether the upper bound is included;
  3. the required output shape;
  4. the expected data type;
  5. a small check for those properties.

These checks catch mistakes such as using 6 as the excluded upper bound for a six-sided die or requesting (features, examples) when later code expects (examples, features).

Exercise: Predict a random array shape

What shape does rng.random((2, 3)) produce?

Answer it first, then check.

HintRead the size argument

The method receives the shape tuple (2, 3).

SolutionThe shape is (2, 3)

The first dimension has length 2 and the second has length 3, so the output contains two rows and three columns.

Exercise: Identify the possible integers

Which set contains every possible value from rng.integers(-2, 3, size=20)?

Choose the possible values

Select one choice, then check.

HintExclude the upper bound

integers(low, high) includes low but does not include high.

SolutionUse the half-open interval

The condition is -2 <= value < 3, so the possible integers are -2, -1, 0, 1, and 2.

Exercise: Separate a guarantee from one draw

Which property is guaranteed by rng.random(100)?

Choose the guarantee

Select one choice, then check.

HintCheck what every draw must satisfy

A small uniform sample can have an uneven appearance and a mean different from 0.5.

SolutionThe interval is guaranteed

Every value lies in [0.0, 1.0). Uniformity describes probabilities across the interval; it does not force one sample to have exact spacing or mean.

Exercise: Scale a uniform draw

Which expression produces floating-point values in [-3.0, 5.0)?

Choose the expression

Select one choice, then check.

HintUse lower + unit draw times width

The required width is 5.0 - (-3.0).

SolutionScale by eight and shift by negative three

Multiplying [0.0, 1.0) by 8.0 gives [0.0, 8.0). Adding -3.0 produces [-3.0, 5.0).

Exercise: Construct and verify simulated rolls

Complete the program so rolls contains a 3 by 4 array of simulated six-sided die rolls. Do not print one expected random array. Instead, print the shape, number of values, and whether every value is valid:

shape: (3, 4)
count: 12
valid: True

Generate values and check their contract

Ready to run.

HintUse integers with an excluded upper bound

Call rng.integers(1, 7, size=(3, 4)).

SolutionGenerate the array and verify its contract

The bounds 1 and 7 produce values from 1 through 6. The size tuple produces twelve values arranged as three rows and four columns. The Boolean check verifies every generated value without assuming an exact sequence.

Retain the generation contract

For each generated array, record or verify:

generator method
+ value range or distribution
+ output shape
+ data type
= the generated-data contract

The contract states what every acceptable result must satisfy. A seed and the generator's sequence state determine which acceptable values appear in one particular run.