Generating Random Floating-Point Numbers with random.random()
random.randint(low, high) generates a random integer within an inclusive range, including both the low and high endpoints.
A Number That Changes Each Call
Random-number functions are useful when a program must make a choice that is not fixed in advance. Python's random.random() produces a pseudorandom floating-point number between 0.0 and 1.0. The value may look unpredictable, but each call produces the next value determined by the random module's internal state.
What do you think happens?
If a loop calls random.random() three times, will all three calls return the same value?
Reveal answer
Answer: No. Each call returns a new pseudorandom float and advances the random module's internal state.
The values appear unpredictable, but they belong to a deterministic sequence determined by the module's state. Without resetting the seed, another run can produce a different sequence.
The Output Interval
random.random() generates 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.
A result can be exactly 0.0, but it will never be exactly 1.0. Other results lie between those boundaries. This half-open interval is useful when scaling the result: multiplying by 100 produces a float in [0.0, 100.0), while multiplying by 6 and converting to an integer can produce one of 0, 1, 2, 3, 4, or 5.
The printed value is not fixed in advance. A valid run might display a value such as 0.37, but the exact result depends on the random module's internal state. The important check is that the result is at least 0.0 and less than 1.0.
Following the Internal State
Every call to random.random() is a separate event. The random module maintains internal state, and that state changes as calls are made. The next call uses the new state to determine the next pseudorandom float. The function does not need to remember the previous value as a variable; the module's internal state controls what comes next.
import random for step in range(3): value = random.random() print(value)
When Expected Output Diverges
When actual random output differs from a sequence you expected, the divergence occurs at the call to random.random() itself. The cause can be an unset seed, a different seed, or a different number of random calls made before the code under inspection runs. The surrounding loop may be working correctly; the pseudorandom value entering the loop's output is what differs.
Suppose you expected five values: [0.1, 0.2, 0.3, 0.4, 0.5]. Instead, the program produced [0.7, 0.8, 0.9, 0.6, 0.5]. The first divergence is the first call to random.random(): the actual first value is 0.7 rather than the expected 0.1. This does not by itself indicate a bug in the loop. To reproduce the earlier sequence, use the same seed that produced it.
Integer Boundaries with randint()
random.randint(low, high) generates a random integer in an inclusive range. Both endpoints are possible. For random.randint(5, 10), the possible results are 5, 6, 7, 8, 9, and 10, and each has a 1-in-6 chance on any given call.
| Expression | Possible endpoint behavior |
|---|---|
| random.randint(5, 10) | 5 and 10 can both be returned |
| range(5, 10) | 5 is included and 10 is excluded |
The upper boundary is handled differently by randint() and range().
The same inclusive-boundary idea can represent a real-world integer choice. For example, random.randint(1, 100) can select an integer from 1 through 100, including both 1 and 100. Use randint() when the endpoints belong to the requested set of possible integer results.
Mistakes in Random Calls
Forgetting to import the random module
The name random is not available until the module has been imported.
Fix:
Write import random before calling random.randint() or random.random().Treating randint() like range() and excluding the high value
randint() includes both its low and high endpoints.
Fix:
Expect 1, 2, 3, 4, 5, or 6 from random.randint(1, 6).Passing the boundaries in the wrong order
The call does not express the intended low-to-high range.
Fix:
Place the lower integer first and the higher integer second.Passing non-integer arguments to randint()
randint() requires integer parameters.
Fix:
Pass integer values such as random.randint(1, 6).Expecting random.random() to return exactly 1.0
The upper boundary of random.random() is exclusive.
Fix:
Treat the result as a value in [0.0, 1.0), where 0.0 is included and 1.0 is not.
Practice and Recap
Write a short Python program that imports random, calls random.random() four times in a loop, and prints each result. Before running it, write down the range every printed value must satisfy. Then explain why your exact four values may differ if you run the program again.
Hints
- Use for and range() to repeat the call four times.
- Each result must be at least 0.0 and less than 1.0.
- The internal state of the random module advances after each call.
- Use the same seed before both runs if you need identical sequences.
- random.random() returns a pseudorandom float in [0.0, 1.0): 0.0 is possible, while 1.0 is excluded. Each call advances the random module's internal state and returns the next value in its pseudorandom sequence. Without resetting the seed, separate runs can produce different sequences; using the same seed makes sequences reproducible. When debugging, locate the first call whose result differs from your expectation. For integer choices, random.randint(low, high) includes both endpoints, unlike range(), which excludes its upper endpoint.
Key Takeaways
- random.random() generates a pseudorandom float in the half-open interval [0.0, 1.0).
- The lower boundary 0.0 is included, while the upper boundary 1.0 is excluded.
- Repeated calls advance the random module's internal state and produce successive values from a pseudorandom sequence.
- Setting the same seed before repeated runs makes the sequence reproducible.
- random.randint(low, high) includes both integer endpoints, unlike range(), and requires integer arguments.