Concepts / Setting Seeds for Reproducible Randomness

Setting Seeds for Reproducible Randomness

Random-looking does not mean unreproducible. Setting the same seed before the same calls produces identical sequences.

  • Programming
Interactive lab

Try it: random.seed and the Mersenne Twister

Python's random module is a deterministic generator: random.seed(n) sets the Mersenne Twister's internal state, and every random(), randint(), choice() and shuffle() consumes 32-bit outputs from it in order — so the same seed replays the same sequence and a different seed gives a different one.

How it works

  1. random.seed(n) splits |n| into 32-bit words and runs MT19937's init_by_array, filling the 624-word state.
  2. Each 32-bit output takes the next state word and tempers it; after 624 words the whole state is regenerated (the twist).
  3. random() joins two outputs: with , , a float in [0.0, 1.0).
  4. randint(a, b) = a + _randbelow(b − a + 1); choice(seq) = seq[_randbelow(len(seq))]; _randbelow(n) keeps the top n.bit_length() bits and rejects values ≥ n.
  5. shuffle walks i from the end down to 1 and swaps x[i] with x[_randbelow(i + 1)].
  6. Replaying the program with a second seed shows where the sequences agree or first diverge.

Default run (11 steps): A program of 5 random-module calls, run after random.seed(42). … Replay with random.seed(42): every result is identical — same seed, same state, same sequence.

Simplified: Seeds are non-negative integers below (one key word), at most 8 calls, randint bounds within ±1000, and lists of up to 8 simple items. Only mt[0..3] and mt[623] of the 624-word state vector are shown (abbreviated). Everything else follows CPython 3.12's random module exactly.

Educational simulation

Loading the simulation…

Why Random Output Can Repeat

A value produced by random.random() looks unpredictable, but it is not produced without a process. Each call returns the next value in a deterministic sequence based on the random module's internal state. Different runs generally produce different sequences unless you set a seed with random.seed() before calling random.random().

Key point

Random-looking does not mean unreproducible. Setting the same seed before the same calls produces identical sequences.

Seed valuesame valueSeed valuesame valueInternal statestate after seedingInternal statestate after seedingFloat sequencevalue 1, value 2, value 3Float sequencevalue 1, value 2, value 3setscalls producesetscalls produce
How does setting the same seed cause random.random() to produce the same sequence across separate runs?

The Value Each Call Returns

random.random() generates a pseudorandom float in the range [0.0, 1.0). The word pseudorandom describes a value that appears random while belonging to a deterministic sequence controlled by the random module's internal state.

Definition

The notation [0.0, 1.0) means that 0.0 is included and 1.0 is excluded. A call can return exactly 0.0, but it will never return exactly 1.0.

0.0includedValues betweenpossible floats1.0excludedthroughapproaches but excludes
Where can each generated float appear on a number line, and why is 0.0 possible while 1.0 is excluded?
In the real world

The range can be scaled. Multiplying a generated value by 100 gives a float in [0.0, 100.0). Multiplying by 6 and converting to an integer gives one of 0, 1, 2, 3, 4, or 5, which can be useful for simulating a die roll.

Following the Generator Through a Loop

A loop is a straightforward way to observe random.random(). If the loop calls the function 10 times, it prints 10 random floats, one per iteration. Every value is in [0.0, 1.0), but the exact values depend on the random module's internal state and can differ from values seen in another run.

Iteration 1random.random()Float 1[0.0, 1.0)Iteration 2random.random()Float 2[0.0, 1.0)Iteration 3random.random()Float 3[0.0, 1.0)returnsinternal state advancesreturnsinternal state advancesreturns
What changes after each loop iteration, and which output value comes next?
Worked example

Tracing Three Calls

Imagine a loop that calls random.random() three times.

  1. 1
    First iteration

    The first call returns the next float determined by the random module's current internal state.

  2. 2
    Second iteration

    The second call returns a new float. The internal state has changed because the first call occurred.

  3. 3
    Third iteration

    The third call returns the next float in the sequence after the second call, and the internal state advances again.

Result

The loop produces three floats. Each call is a separate event, and the next value depends on the state left by the preceding call.

What do you think happens?

If the same code is run twice without resetting the seed, should you expect the two runs to produce identical sequences?

  • Yes, because the loop is the same

  • No, because the random module's state is not reset

  • Yes, because every call returns the same value

Reveal answer
Answer:

No, because the random module's state is not reset.

The source material states that running the same code twice without resetting the seed produces different sequences. Setting the same seed before both runs produces identical sequences.

Reproducing a Sequence

To reproduce an exact sequence, set the seed with random.seed() before the sequence of random.random() calls begins. When the same seed is set before the same sequence of calls, the random module starts from the corresponding same state and produces identical values in the same order.

SetupExpected sequence behavior
Same seed before the same callsIdentical sequences
No seed reset between runsDifferent sequences can occur
Different seedThe sequence can differ
Different number of earlier random callsLater output can differ because the internal state differs

How setup affects reproducibility

Finding the Divergence Point

When actual output differs from an expected sequence, locate the first random.random() call that returned a different value. That is the divergence point. The difference comes from the random module having a different internal state, which can happen when the seed was not set, a different seed was used, or a different number of random calls occurred before the code ran.

Call 1expected and actual matchCall 2expected and actual differCall 3later values follow thechanged statenext callnext call
At which call do two random-number sequences diverge when their seeds, call counts, or generator states differ?
Worked example

Comparing Expected and Actual Values

Suppose five expected values are [0.1, 0.2, 0.3, 0.4, 0.5], while the observed values are [0.7, 0.8, 0.9, 0.6, 0.5]. Where does the sequence first diverge?

  1. 1
    Compare the first call

    The expected first value is 0.1, but the observed first value is 0.7.

  2. 2
    Mark the divergence

    The first call to random.random() is the divergence point because it produced a different value immediately.

  3. 3
    Interpret the cause

    The random module's internal state was different from the state that produced the expected sequence.

Result

The divergence occurred at the first random.random() call. Reproducing the expected sequence requires setting the same seed that produced it previously.

  • Common mistake

    Assuming a random-looking value is unrelated to previous calls.

    What it looks like

    Treating each call as if it starts a completely new process.

    Why it fails

    The random module maintains internal state, and each call returns the next value in a deterministic sequence based on that state.

    Do this instead

    Trace each call in order and remember that every call advances the internal state.

  • Common mistake

    Expecting identical output from repeated runs without resetting the seed.

    What it looks like

    Running the same loop twice and expecting the same values in both runs.

    Why it fails

    The source states that runs without resetting the seed produce different sequences.

    Do this instead

    Set the same seed before both sequences when reproducible output is needed.

  • Common mistake

    Treating 1.0 as a possible result.

    What it looks like

    Describing the output range as including both 0.0 and 1.0.

    Why it fails

    The interval uses a parenthesis at 1.0, so the upper bound is exclusive.

    Do this instead

    Read [0.0, 1.0) as including 0.0 and excluding 1.0.

  • Common mistake

    Searching for the divergence somewhere after the generated value.

    What it looks like

    Debugging later loop logic before checking the random.random() call that first differed.

    Why it fails

    The divergence occurs at the call where the pseudorandom value is generated.

    Do this instead

    Compare expected and actual values in order and identify the first differing random.random() call.

Check Your Understanding

MEDIUM

A loop calls random.random() three times. Explain what happens to the random module's internal state after each call, state the valid range for each returned value, and describe what you would change to make a second run reproduce the first run's sequence.

Hints
  • Each call returns the next value in the sequence.
  • The range includes 0.0 and excludes 1.0.
  • Use random.seed() before the loop, using the same seed before both runs.

Key Takeaways

  1. 1
    random.random() returns a pseudorandom float in [0.0, 1.0).
  2. 2
    The lower bound 0.0 is included, while the upper bound 1.0 is excluded.
  3. 3
    Every call returns the next value and advances the random module's internal state.
  4. 4
    The same seed before the same calls produces the same sequence.
  5. 5
    When output differs from expectation, find the first random.random() call where the values diverge.

At a glance

  • random.random() generates pseudorandom floats from 0.0 inclusive up to, but not including, 1.0.
  • Repeated calls move through a deterministic sequence controlled by the random module's internal state.
  • Setting the same seed before repeated runs makes their sequences reproducible.
  • The first differing random.random() call marks the divergence point during debugging.

Related concepts

More concepts starting with S