random number including 1 - i.e. [0,1]

Steven D'Aprano steven at REMOVE.THIS.cybersource.com.au
Wed Jun 10 22:06:16 EDT 2009

On Wed, 10 Jun 2009 15:32:05 -0500, Robert Kern wrote:

> That's a fair point. However, one issue that hasn't been brought up is
> that it might be confusing to a user why random.random() returns values
> in a half-open interval while random.uniform() claims a closed interval.
> Even for reasonably sophisticated floating point users, it's not
> necessarily obvious that that is the reasoning behind the different
> claims.

Agreed -- the reasoning that a half-open interval [0, 1) for z (random())
leads to a closed interval [a, b] for a+(b-a)*z (uniform()) is *not* 
obvious even for people who are aware that floats do funny things. I know 
I got caught out by it. 

However, rather than a documentation patch, I'd prefer to see uniform() 
fixed to return a value in the half-open interval. Something like:

    def uniform(self, a, b):
        """Get a random number in the range [a, b)."""
        r = a + (b-a) * self.random()
        while r == b:  # Guard against (rare) rounding to b.
            r = a + (b-a) * self.random()
        return r

should do the trick. I think.

Earlier, Mark Dickinson wrote:

"Can you think of a single practical situation where it would matter 
that, for some values of a and b, uniform(a, b) can never produce the 
value b?"

I would argue that it is a good thing if uniform never returns b.

alist[ int(uniform(0, len(alist))) ]

can apparently fail for some lists, but not others.

Admittedly, I don't have a good reason for using the above rather than 
sample(), or for truncating the result of uniform() rather than using 
randrange(). Hopefully if I don't mention it, nobody will notice it... 


More information about the Python-list mailing list