Other answers have pointed out that the result of random()
is always strictly less than 1.0
; however, that's only half the story.
If you're computing randrange(n)
as int(random() * n)
, you also need to know that for any Python float x
satisfying 0.0 <= x < 1.0
, and any positive integer n
, it's true that 0.0 <= x * n < n
, so that int(x * n)
is strictly less than n
.
There are two things that could go wrong here: first, when we compute x * n
, n
is implicitly converted to a float. For large enough n
, that conversion might alter the value. But if you look at the Python source, you'll see that it only uses the int(random() * n)
method for n
smaller than 2**53
(here and below I'm assuming that the platform uses IEEE 754 doubles), which is the range where the conversion of n
to a float is guaranteed not to lose information (because n
can be represented exactly as a float).
The second thing that could go wrong is that the result of the multiplication x * n
(which is now being performed as a product of floats, remember) probably won't be exactly representable, so there will be some rounding involved. If x
is close enough to 1.0
, it's conceivable that the rounding will round the result up to n
itself.
To see that this can't happen, we only need to consider the largest possible value for x
, which is (on almost all machines that Python runs on) 1 - 2**-53
. So we need to show that (1 - 2**-53) * n < n
for our positive integer n
, since it'll always be true that random() * n <= (1 - 2**-53) * n
.
Proof (Sketch) Let k
be the unique integer k
such that 2**(k-1) < n <= 2**k
. Then the next float down from n
is n - 2**(k-53)
. We need to show that n*(1-2**53)
(i.e., the actual, unrounded, value of the product) is closer to n - 2**(k-53)
than to n
, so that it'll always be rounded down. But a little arithmetic shows that the distance from n*(1-2**-53)
to n
is 2**-53 * n
, while the distance from n*(1-2**-53)
to n - 2**(k-53)
is (2**k - n) * 2**-53
. But 2**k - n < n
(because we chose k
so that 2**(k-1) < n
), so the product is closer to n - 2**(k-53)
, so it will get rounded down (assuming, that is, that the platform is doing some form of round-to-nearest).
So we're safe. Phew!