2010-04-02 8 views
32

Mi è sempre sembrato strano che random.randint(a, b) restituisse un numero intero nell'intervallo [a, b], anziché [a, b-1] come range(...).Python: perché `random.randint (a, b)` restituisce un intervallo comprensivo di `b`?

C'è qualche motivo per questa apparente incoerenza?

+6

(Non risponde alla domanda :) Bene, è possibile utilizzare 'randrange'. – kennytm

+0

Forse non sono così esperto come te, ma non lo vedo come un'incoerenza. Lo vedo come un semplice metodo per i programmatori di chiamare un numero compreso casualmente senza bisogno di usare operatori e numeri magici. Le lingue migliori offrono ai loro utenti le strade attraverso le quali possono essere creativi. – Musixauce3000

+0

@ Musixauce3000 è un'incoerenza perché entrambi i metodi - 'range' e' randint' - accettano lo stesso valore logico (cioè un intervallo di numeri), ma quel valore è specificato in due modi diversi - incoerenti - (uno è compreso del punto finale, l'altro è esclusivo). –

risposta

64

Ho cercato di arrivare a fondo esaminando alcune vecchie fonti. Ho il sospetto che randint è stato attuato prima intero long di Python: il che significa che se si voleva un numero casuale che comprendeva INT_MAX, si avrebbe bisogno di chiamare random.randrange(0, INT_MAX + 1) che sarebbe traboccato e ha portato in argomenti di (0, 0) o (0, INT_MIN) seconda.

Tuttavia, guardando nel lontano anche the Python 1.5.2 sources, in Lib/whrandom.py vediamo:

# 
# 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 è stato continuato ad essere obsoleta in 2.0, 2.1, 2.2 e 2.3; ma random.randint è stato contrassegnato come deprecato in 2.1, anche se non è più contrassegnato come deprecato in 2.2.

Inoltre, random.py from version 2.1 è il primo a notare in docstring 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. 
    """ 

L'unica fonte disponibile di età superiore cioè the 0.9.1 source, e per quanto ne so, randint non è stato attuato in quel punto .

Quindi, concludo che il ragionamento per randintincluso l'endpoint è noto al solo Guido stesso a questo punto; data la docstring di Python 2.1, sembra che il motivo potrebbe essere stato un semplice errore.

+4

+1 per fare lo sforzo di ricercare questo, con alcune osservazioni interessanti. –

+0

Sì, questa è un'ottima risposta. Molte grazie! –

+0

Forse le specifiche randint provengono da un'altra lingua? –

3

Non credo che ci sia un motivo per questo. Ma almeno è documentato.

+1

+1: E il motivo non ha importanza. Anche se non è documentato, non ha importanza. –

10

Immagino che il random.randint sia stato il primo tentativo di implementare questa funzione. Sembra che gli sviluppatori Python anche sentito che questo era un problema, ed è per questo in v1.5.2 hanno aggiunto un altro metodo randrange con più parametri standard:

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

Return un elemento scelto a caso dalla distanza (start, stop, passaggio). Questo è equivalente alla scelta (intervallo (start, stop, step)), ma in realtà non costruisce un oggetto range.

È possibile utilizzare randrange invece di randint di evitare le persone sorprendenti.

D'altra parte, in molte situazioni in cui il problema è formulata come 'scegliere un numero casuale compreso tra 1 e 6' potrebbe essere più naturale da usare randint(1, 6) invece di scrivere randrange(1, 7) o randrange(min, max + 1).

6

Questa è la speculazione, ma il normale utilizzo umano di "Dammi un numero casuale da A a B" è comprensivo.L'implementazione in questo modo ha un senso, data la filosofia generale di Python di essere un linguaggio più leggibile.

Problemi correlati