Python: почему `random.randint (a, b)` возвращает диапазон, включающий `b`? - PullRequest
36 голосов
/ 02 апреля 2010

Мне всегда казалось странным, что random.randint(a, b) возвращает целое число в диапазоне [a, b] вместо [a, b-1], как range(...).

Есть ли какая-либо причина для этого очевидного несоответствия?

Ответы [ 4 ]

74 голосов
/ 03 апреля 2010

Я попытался разобраться в этом, изучив некоторые старые источники. Я подозревал , что randint было реализовано перед длинным целым числом Python: это означает, что если бы вы хотели случайное число, включающее INT_MAX, вам нужно было бы вызвать random.randrange(0, INT_MAX + 1), что привело бы к переполнению и привело бы к аргументам (0, 0) или (0, INT_MIN) в зависимости.

Однако, оглядываясь назад даже на исходники Python 1.5.2 , в Lib/whrandom.py мы видим:

#
# 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 продолжал быть устаревшим в 2,0 , 2,1 , 2,2 и 2,3 ; но random.randint был помечен как устаревший в 2.1 , хотя больше не помечен как устаревший в 2.2 .

Кроме того, random.py с версии 2.1 является первым, кто заметил в строке документа random.randint:

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.
    """

Единственный доступный источник старше этого - источник 0.9.1 , и, насколько я могу судить, randint не был реализован в этот момент.

Таким образом, я заключаю, что обоснование randint , включая конечную точку, известно только самому Гвидо в этой точке; учитывая строку документации из Python 2.1, похоже, что причиной могла быть простая ошибка.

10 голосов
/ 02 апреля 2010

Я думаю, random.randint была только первой попыткой реализации этой функции. Похоже, что разработчики Python также чувствовали, что это проблема, поэтому в v1.5.2 они добавили еще один метод randrange с более стандартными параметрами:

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

Возвращает случайно выбранный элемент из диапазона (начало, остановка, шаг). Это эквивалентно выбору (диапазон (начало, остановка, шаг)), но фактически не создает объект диапазона.

Вы можете использовать randrange вместо randint, чтобы избежать удивления людей.

С другой стороны, во многих ситуациях, когда проблема формулируется как «выберите случайное число от 1 до 6», было бы более естественно использовать randint(1, 6) вместо записи randrange(1, 7) или randrange(min, max + 1).

7 голосов
/ 03 апреля 2010

Это предположение, но обычное человеческое использование «дай мне случайное число от a до b» включительно. Такая реализация имеет смысл, учитывая общую философию Python о том, чтобы быть более понятным для человека языком.

3 голосов
/ 02 апреля 2010

Я не думаю, что есть причина для этого. Но, по крайней мере, это задокументировано.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...