Module 5 · Lesson 5

Random Number Generation with the Generator API

Modern NumPy code should create an explicit Generator instead of using the legacy global functions (np.random.seed, np.random.rand, …):

rng = np.random.default_rng(seed=42)

A Generator gives you reproducibility (same seed -> same sequence) and independent streams (two default_rng() calls never silently share or clobber global state, which matters once you have multiple pieces of code sampling randomness at once). The most common methods:

MethodProduces
rng.random(size)floats uniform in [0, 1)
rng.integers(low, high, size)integers in [low, high)
rng.normal(loc, scale, size)samples from a normal distribution
rng.choice(a, size, replace=...)random samples from an array

For rng.choice, replace=True (the default) can pick the same element more than once; replace=False samples without repeats, like dealing cards from a deck instead of rolling the same die repeatedly.

rng = np.random.default_rng(seed=42)
print(rng.random(3))
print(rng.integers(0, 10, size=5))
print(rng.normal(loc=0.0, scale=1.0, size=3))

# same seed -> same sequence, every time
rng_a = np.random.default_rng(seed=7)
rng_b = np.random.default_rng(seed=7)
print(np.array_equal(rng_a.random(5), rng_b.random(5)))

samples = np.random.default_rng(0).normal(size=10_000)
plt.hist(samples, bins=30)
plt.title("10,000 samples from a standard normal distribution")
plt.show()

Output:

[0.77395605 0.43887844 0.85859792]
[0 6 2 0 5]
[ 0.1278404  -0.31624259 -0.01680116]
True
plot output
5.1

Reproducible dice rolls

Write roll_dice(n_rolls, seed) that returns an array of n_rolls simulated six-sided die rolls (integers 1-6 inclusive), using np.random.default_rng(seed). The same seed must always produce the same sequence.

💡 Hint

np.random.default_rng(seed).integers(1, 7, size=n_rolls) — remember integers's upper bound is exclusive, so use 7 to include 6.

✅ Solution
def roll_dice(n_rolls, seed):
    rng = np.random.default_rng(seed)
    return rng.integers(1, 7, size=n_rolls)
5.2

Shuffle without replacement

Write random_sample_no_replace(arr, k, seed) that returns k elements randomly chosen from arr without replacement (no duplicates), using rng.choice with the right arguments.

💡 Hint

np.random.default_rng(seed).choice(arr, size=k, replace=False).

✅ Solution
def random_sample_no_replace(arr, k, seed):
    rng = np.random.default_rng(seed)
    return rng.choice(arr, size=k, replace=False)