2010-04-02 9 views
32

Siempre me ha parecido extraño que random.randint(a, b) devuelva un número entero en el rango [a, b], en lugar de [a, b-1] como range(...).Python: ¿por qué `random.randint (a, b)` devuelve un rango que incluye `b`?

¿Hay alguna razón para esta aparente inconsistencia?

+6

(No respondiendo a la pregunta :) Bueno, podrías usar 'randrange'. – kennytm

+0

Tal vez no soy tan inteligente como usted, pero no lo veo como una incoherencia. Lo veo simplemente como un método para que los programadores llamen a un número inclusivo al azar sin necesidad de utilizar operadores y números mágicos. Los mejores idiomas dan a sus usuarios vías a través de las cuales pueden ser creativos. – Musixauce3000

+0

@ Musixauce3000 es una inconsistencia porque ambos métodos - 'range' y' randint' - aceptan el mismo valor lógico (es decir, un rango de números), pero ese valor se especifica de dos maneras diferentes (inconsistentes) (es decir, uno es inclusivo del punto final, el otro es exclusivo). –

Respuesta

64

Intenté llegar al fondo de esto examinando algunas fuentes antiguas. Yo sospechaba que randint se puso en práctica en poco tiempo entero de Python: lo que significa que si usted quiere un número aleatorio que incluyó INT_MAX, que habría necesitado para llamar random.randrange(0, INT_MAX + 1) que habría desbordado y dio lugar a argumentos de (0, 0) o (0, INT_MIN) función.

Sin embargo, mirando ya en the Python 1.5.2 sources incluso, en Lib/whrandom.py vemos:

# 
# 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 se continuó a ser obsoleto en 2.0, 2.1, 2.2 y 2.3; pero random.randint se marcó como obsoleto en 2.1, aunque ya no se marcó como obsoleto en 2.2.

Además, random.py from version 2.1 es el primero en observar en cadena de documentación random.randint 's:

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 única fuente disponible más antigua que es the 0.9.1 source, y por lo que puedo decir, randint no se puso en práctica en ese punto .

Por lo tanto, llego a la conclusión de que el razonamiento para randintque incluye el punto final es conocido por el propio Guido en este momento; dado el docstring de Python 2.1, parece que la razón pudo haber sido un simple error.

+4

+1 por hacer el esfuerzo de investigar esto, con algunas observaciones interesantes. –

+0

Sí, esa es una gran respuesta. ¡Muchas gracias! –

+0

¿Tal vez la especificación Randint vino de otro idioma? –

3

No creo que haya una razón para eso. Pero al menos está documentado.

+1

+1: Y la razón no importa. Incluso si no está documentado, aún no importa. –

10

Supongo que random.randint fue solo el primer intento de implementar esta característica. Parece que los desarrolladores de Python también sabían que este era un problema, por lo que en v1.5.2 agregaron otro método randrange con más parámetros estándar:

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

devolver un elemento seleccionado al azar de la gama (Inicio, parar, paso). Esto es equivalente a la elección (rango (inicio, parada, paso)), pero en realidad no construye un objeto rango.

Puede usar randrange en lugar de randint para evitar sorprender a las personas.

Por otra parte, en muchas situaciones donde el problema se formula como 'elegir un número aleatorio entre 1 y 6' podría ser más natural utilizar randint(1, 6) en lugar de escribir randrange(1, 7) o randrange(min, max + 1).

6

Esto es una especulación, pero el uso humano normal de 'darme un número aleatorio de aa b' es inclusivo.Implementarlo de esa manera tiene sentido, dada la filosofía general de Python de ser un lenguaje más legible para los humanos.

Cuestiones relacionadas