Understanding Float Data Types
random.random() generates a pseudorandom float in the range [0.0, 1.0), inclusive of 0.0 but exclusive of 1.0
A New Value at Each Call
The function random.random() generates a pseudorandom float. Each time the function is called, it returns a new value. The values appear unpredictable, but they come from a deterministic sequence controlled by the random module's internal state.
The call produces one floating-point value and assigns it to value. The exact number depends on the random module's current internal state, so a different run can produce a different result.
The Half-Open Output Range
random.random() returns a pseudorandom float in the range [0.0, 1.0). The square bracket means that 0.0 is included. The parenthesis means that 1.0 is excluded.
The notation [0.0, 1.0) describes a half-open range: the lower endpoint belongs to the range, while the upper endpoint does not. Therefore, a result of exactly 0.0 is allowed, but a result of exactly 1.0 is not.
Reading the Range Notation
Determine whether each listed value could be returned by random.random(): 0.0, 0.42, and 1.0.
Check 0.0: The opening square bracket includes 0.0, so this value is allowed.
Check 0.42: This value lies between 0.0 and 1.0, so it is allowed.
Check 1.0: The closing parenthesis excludes 1.0, so this value is not returned by random.random().
0.0 and 0.42 are possible results; 1.0 is not.
Tracing a Repeated Call
A loop makes the behavior easier to observe because it calls random.random() once per iteration. The following generated example uses three iterations so that the sequence is easy to trace.
import random for iteration in range(3): value = random.random() print(value)
The important state change is inside the random module. Each call advances the module's internal state, and that changed state determines the next value. The function itself does not remember the previous value; the random module maintains the state used to produce the next one.
What do you think happens?
A loop calls random.random() three times. How many pseudorandom floats will it print?
Reveal answer
Answer: Three
The function is called once during each of the three loop iterations, so the loop prints three values. Their exact numeric values are not fixed unless the random sequence is reproduced with the same seed and call history.
Reproducible and Variable Sequences
The sequence is pseudorandom rather than truly unpredictable in the programming sense. Each call returns the next value in a deterministic sequence based on the random module's internal state. However, different runs produce different sequences unless random.seed() is set before the calls.
| Setup | Observed behavior |
|---|---|
| No seed is set before the calls | Different runs produce different sequences. |
| The same seed is set before both runs | Both runs produce identical sequences. |
| The seed or number of earlier calls differs | The internal state differs, so the later sequence can differ. |
This example sets a seed before the loop. The source material does not specify the numeric output for seed 7, so the important result here is reproducibility: running the same setup again with the same seed produces the same sequence, provided the calls before and inside the loop are the same.
Finding the Divergence Point
When actual output differs from an expected sequence, inspect the calls to random.random() first. The divergence occurs at the call that generates the different value, not somewhere later in the printing or loop structure.
Comparing Expected and Actual Values
Suppose five generated values were expected to be [0.1, 0.2, 0.3, 0.4, 0.5], but the program produced [0.7, 0.8, 0.9, 0.6, 0.5]. Where did the sequences first diverge?
Compare the first values: The expected first value is 0.1, while the actual first value is 0.7.
Locate the first differing call: The first call to random.random() produced a different value, so that is the first divergence point.
Interpret the cause: The random module's internal state was different. Possible reasons include not setting the seed, using a different seed, or making a different number of random calls before this sequence.
The divergence occurred at the first call to random.random(), not later in the output process.
Mistakes Beginners Make
Treating 1.0 as a possible result.
The closing parenthesis excludes 1.0.
Fix:
Remember that 0.0 is included and 1.0 is excluded.Expecting the same sequence every time without setting a seed.
Different runs can begin with different internal states.
Fix:
Set the same seed before the calls when reproducibility is required.Searching for the divergence after the random value has already been generated.
The divergence begins at the random.random() call that returned the unexpected value.
Fix:
Compare values in call order and inspect the seed and earlier random calls.Assuming the function repeats its previous result.
Each call returns the next value in the sequence determined by the changing internal state.
Fix:
Treat every call as a separate event that advances the random module's state.
Practice the Trace
Consider a loop that calls random.random() once per iteration for four iterations. Describe how many floats are printed, the allowed range of every value, and what happens to the random module's internal state after each call. Then explain what you would check first if your actual first value differs from an expected first value.
Hints
- Count the number of loop iterations.
- Use the notation [0.0, 1.0) to identify the allowed values.
- The first divergence is located at the call that generated the first unexpected value.
- Check whether the seed and the number of earlier random calls match the expected setup.
Practice Answer
Answer the four-iteration trace question.
Count outputs: There is one call in each of four iterations, so four floats are printed.
Check the range: Every returned value is in [0.0, 1.0): 0.0 is possible, and 1.0 is excluded.
Track state: Each call advances the random module's internal state, which determines the next value.
Debug the mismatch: If the first actual value differs from the expected first value, the divergence occurs at the first random.random() call. Check the seed and any earlier calls.
Four calls produce four pseudorandom floats, each call advances internal state, and the first unexpected value identifies the first divergence.
Key Takeaways
- random.random() returns a pseudorandom float in the half-open range [0.0, 1.0).
- The lower bound 0.0 is included, while the upper bound 1.0 is excluded.
- Each call returns the next value in a deterministic sequence based on the random module's internal state.
- A loop calling random.random() once per iteration produces one new float per iteration and advances the internal state each time.
- Use random.seed() to reproduce a sequence, and identify the first unexpected random.random() result as the divergence point when debugging.