Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Python: why does `random.randint(a, b)` return a range inclusive of `b`?

It has always seemed strange to me that random.randint(a, b) would return an integer in the range [a, b], instead of [a, b-1] like range(...).

Is there any reason for this apparent inconsistency?

like image 969
David Wolever Avatar asked Apr 02 '10 19:04

David Wolever


People also ask

Is random Randint Python inclusive?

randint() function to get a random integer number from the inclusive range. For example, random. randint(0, 10) will return a random number from [0, 1, 2, 3, 4, 5, 6, 7, 8 ,9, 10].

What does random Randint return?

Python Random randint() Method The randint() method returns an integer number selected element from the specified range. Note: This method is an alias for randrange(start, stop+1) .

What does Randint return in Python?

Basically, the randint() method in Python returns a random integer value between the two lower and higher limits (including both limits) provided as two parameters. It should be noted that this method is only capable of generating integer-type random value.

Is random Randrange inclusive?

The only differences between randrange and randint that I know of are that with randrange([start], stop[, step]) you can pass a step argument and random. randrange(0, 1) will not consider the last item, while randint(0, 1) returns a choice inclusive of the last item.


4 Answers

I tried to get to the bottom of this by examining some old sources. I suspected that randint was implemented before Python's long integer: meaning that if you wanted a random number that included INT_MAX, you would have needed to call random.randrange(0, INT_MAX + 1) which would have overflowed and resulted in arguments of (0, 0) or (0, INT_MIN) depending.

However, looking as far back as even the Python 1.5.2 sources, in Lib/whrandom.py we see:

#
# Get a random integer in the range [a, b] including both end points.
# (Deprecated; use randrange below.)
#
def randint(self, a, b):
    return self.randrange(a, b+1)

whrandom.randint was continued to be deprecated in 2.0, 2.1, 2.2, and 2.3; but random.randint was marked as deprecated in 2.1, although no longer marked as deprecated in 2.2.

Also, random.py from version 2.1 is the first to note in random.randint's docstring:

def randrange(self, start, stop=None, step=1, int=int, default=None):
    """Choose a random item from range(start, stop[, step]).

    This fixes the problem with randint() which includes the
    endpoint; in Python this is usually not what you want.
    Do not supply the 'int' and 'default' arguments.
    """

The only available source older than that is the 0.9.1 source, and as far as I can tell, randint was not implemented at that point.

Thus, I conclude that the reasoning for randint including the endpoint is known to only Guido himself at this point; given the docstring from Python 2.1, it sounds like the reason may have been a simple mistake.

like image 50
Mark Rushakoff Avatar answered Sep 28 '22 10:09

Mark Rushakoff


I guess random.randint was just the first attempt at implementing this feature. It seems that the Python developers also felt that this was a problem, which is why in v1.5.2 they added another method randrange with more standard parameters:

random.randrange([start], stop[, step])

Return a randomly selected element from range(start, stop, step). This is equivalent to choice(range(start, stop, step)), but doesn’t actually build a range object.

You can use randrange instead of randint to avoid surprising people.

On the other hand, in many situations where the problem is phrased as 'choose a random number between 1 and 6' it might be more natural to use randint(1, 6) instead of writing randrange(1, 7) or randrange(min, max + 1).

like image 41
Mark Byers Avatar answered Sep 29 '22 10:09

Mark Byers


I don't think there's a reason for that. But at least it's documented.

like image 40
Wieland Avatar answered Sep 27 '22 10:09

Wieland


This is speculation, but normal human usage of 'give me a random number from a to b' is inclusive. Implementing it that way sort of makes sense, given Python's general philosophy of being a more human-readable language.

like image 39
DNS Avatar answered Sep 27 '22 10:09

DNS