Python: pourquoi aléatoire.randint(a, b)` renvoie une gamme inclusive de "b"?

Il m'a toujours semblé étrange pour moi que random.randint(a, b) renvoie un entier dans l'intervalle [a, b] au lieu de [a, b-1]range(...).

y a-t-il une raison à cette apparente incohérence?

34
demandé sur David Wolever 2010-04-02 23:38:00

4 réponses

j'ai essayé d'aller au fond des choses en examinant de vieilles sources. J' soupçonnésrandint a été implémenté avant le long entier de Python: ce qui signifie que si vous vouliez un nombre aléatoire qui incluait INT_MAX, vous avez besoin d'appeler random.randrange(0, INT_MAX + 1) qui aurait débordé et abouti à des arguments de (0, 0) ou (0, INT_MIN) en fonction.

Cependant, en regardant aussi loin que même le Python 1.5.2 sources, en Lib/whrandom.py nous voir:

#
# 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 a continué à être obsolète dans 2.0, 2.1, 2.2 et 2.3;random.randint a été marquée comme étant dépréciée dans 2.1, bien qu'elle ne soit plus marquée comme étant dépréciée dans 2.2.

Également random.py à partir de la version 2.1 est le premier à noter dans 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.
    """

la seule source disponible plus ancienne est la 0.9.1 source, et aussi loin que je peux dire, randint n'a pas été mis en oeuvre à ce moment-là.

ainsi, je conclus que le raisonnement pour randint le point final n'est connu que de Guido lui-même à ce point; étant donné le docstring de Python 2.1, il semble que la raison ait pu être une simple erreur.

66
répondu Mark Rushakoff 2010-04-02 20:14:34

je pense random.randint n'était que la première tentative d'implémentation de cette fonctionnalité. Il semble que les développeurs de Python ont également pensé que c'était un problème, et c'est pourquoi dans v1.5.2 ils ont ajouté une autre méthode randrange plus de paramètres standard:

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

retourner un élément choisi au hasard à partir de la plage(démarrer, arrêter, pas). C'est l'équivalent du choix(gamme (start, stop, step)), mais ne construit pas réellement une gamme objet.

Vous pouvez utiliser randrange au lieu de randint pour éviter de surprendre les gens.

d'autre part, dans beaucoup de situations où le problème est formulé comme "choisissez un nombre au hasard entre 1 et 6' il serait plus naturel d'utiliser randint(1, 6) au lieu d'écrire randrange(1, 7) ou randrange(min, max + 1).

10
répondu Mark Byers 2010-04-02 20:03:37

c'est de la spéculation, mais l'usage humain normal de "Donnez-moi un nombre aléatoire de a à b" est inclusif. L'implémenter de cette façon a du sens, étant donné la philosophie générale de Python d'être un langage plus lisible par les humains.

6
répondu DNS 2010-04-02 20:25:14

Je ne pense pas qu'il y ait une raison à cela. Mais au moins, c'est documenté.

3
répondu Wieland 2010-04-02 19:42:04