random
--- Generate pseudo-random numbers¶
Code source : Lib/random.py
Ce module implémente des générateurs de nombres pseudo-aléatoires pour différentes distributions.
Pour les entiers, il existe une sélection uniforme à partir d'une plage. Pour les séquences, il existe une sélection uniforme d'un élément aléatoire, une fonction pour générer une permutation aléatoire d'une liste sur place et une fonction pour un échantillonnage aléatoire sans remplacement.
Pour l'ensemble des réels, il y a des fonctions pour calculer des distributions uniformes, normales (gaussiennes), log-normales, exponentielles négatives, gamma et bêta. Pour générer des distributions d'angles, la distribution de von Mises est disponible.
Almost all module functions depend on the basic function random()
, which
generates a random float uniformly in the half-open range 0.0 <= X < 1.0
.
Python uses the Mersenne Twister as the core generator. It produces 53-bit precision
floats and has a period of 2**19937-1. The underlying implementation in C is
both fast and threadsafe. The Mersenne Twister is one of the most extensively
tested random number generators in existence. However, being completely
deterministic, it is not suitable for all purposes, and is completely unsuitable
for cryptographic purposes.
Les fonctions fournies par ce module dépendent en réalité de méthodes d’une instance cachée de la classe random.Random
. Vous pouvez créer vos propres instances de Random
pour obtenir des générateurs sans états partagés.
Class Random
can also be subclassed if you want to use a different
basic generator of your own devising: see the documentation on that class for
more details.
Le module random
fournit également la classe SystemRandom
qui utilise la fonction système os.urandom()
pour générer des nombres aléatoires à partir de sources fournies par le système d'exploitation.
Avertissement
Les générateurs pseudo-aléatoires de ce module ne doivent pas être utilisés à des fins de sécurité. Pour des utilisations de sécurité ou cryptographiques, voir le module secrets
.
Voir aussi
M. Matsumoto and T. Nishimura, "Mersenne Twister: A 623-dimensionally equidistributed uniform pseudorandom number generator", ACM Transactions on Modeling and Computer Simulation Vol. 8, No. 1, Janvier pp.3--30 1998.
Complementary-Multiply-with-Carry recipe for a compatible alternative random number generator with a long period and comparatively simple update operations.
Fonctions de gestion d'état¶
- random.seed(a=None, version=2)¶
Initialise le générateur de nombres aléatoires.
Si a est omis ou
None
, l'heure système actuelle est utilisée. Si des sources aléatoires sont fournies par le système d'exploitation, elles sont utilisées à la place de l'heure système (voir la fonctionos.urandom()
pour les détails sur la disponibilité).Si a est un entier, il est utilisé directement.
Avec la version 2 (par défaut), un objet
str
,bytes
oubytearray
est converti enint
et tous ses bits sont utilisés.Avec la version 1 (fournie pour reproduire des séquences aléatoires produites par d'anciennes versions de Python), l'algorithme pour
str
etbytes
génère une gamme plus étroite de graines.Modifié dans la version 3.2: Passée à la version 2 du schéma qui utilise tous les bits d'une graine de chaîne de caractères.
- random.getstate()¶
Renvoie un objet capturant l'état interne actuel du générateur. Cet objet peut être passé à
setstate()
pour restaurer cet état.
- random.setstate(state)¶
Il convient que state ait été obtenu à partir d'un appel précédent à
getstate()
, etsetstate()
restaure l'état interne du générateur à ce qu'il était au moment oùgetstate()
a été appelé.
Fonctions pour les octets¶
- random.randbytes(n)¶
Génère n octets aléatoires.
Cette méthode ne doit pas être utilisée pour générer des jetons de sécurité. Utiliser
secrets.token_bytes()
à la place.Ajouté dans la version 3.9.
Fonctions pour les entiers¶
- random.randrange(stop)¶
- random.randrange(start, stop[, step])
Return a randomly selected element from
range(start, stop, step)
.This is roughly equivalent to
choice(range(start, stop, step))
but supports arbitrarily large ranges and is optimized for common cases.The positional argument pattern matches the
range()
function.Keyword arguments should not be used because they can be interpreted in unexpected ways. For example
randrange(start=100)
is interpreted asrandrange(0, 100, 1)
.Modifié dans la version 3.2:
randrange()
est plus sophistiquée dans la production de valeurs uniformément distribuées. Auparavant, elle utilisait un style commeint(random()*n)
qui pouvait produire des distributions légèrement inégales.Modifié dans la version 3.12: Automatic conversion of non-integer types is no longer supported. Calls such as
randrange(10.0)
andrandrange(Fraction(10, 1))
now raise aTypeError
.
- random.randint(a, b)¶
Renvoie un entier aléatoire N tel que
a <= N <= b
. Alias pourrandrange(a, b+1)
.
- random.getrandbits(k)¶
Returns a non-negative Python integer with k random bits. This method is supplied with the Mersenne Twister generator and some other generators may also provide it as an optional part of the API. When available,
getrandbits()
enablesrandrange()
to handle arbitrarily large ranges.Modifié dans la version 3.9: Cette méthode accepte désormais zéro pour k.
Fonctions pour les séquences¶
- random.choice(seq)¶
Renvoie un élément aléatoire de la séquence non vide seq. Si seq est vide, lève
IndexError
.
- random.choices(population, weights=None, *, cum_weights=None, k=1)¶
Renvoie une liste de taille k d'éléments choisis dans la population avec remise. Si la population est vide, lève
IndexError
.Si une séquence de poids est spécifiée, les tirages sont effectués en fonction des poids relatifs. Alternativement, si une séquence cum_weights est donnée, les tirages sont faits en fonction des poids cumulés (peut-être calculés en utilisant
itertools.accumulate()
). Par exemple, les poids relatifs[10, 5, 30, 5]
sont équivalents aux poids cumulatifs[10, 15, 45, 50]
. En interne, les poids relatifs sont convertis en poids cumulatifs avant d'effectuer les tirages, ce qui vous permet d'économiser du travail en fournissant des pondérations cumulatives.Si ni weights ni cum_weights ne sont spécifiés, les tirages sont effectués avec une probabilité uniforme. Si une séquence de poids est fournie, elle doit être de la même longueur que la séquence population. Spécifier à la fois weights et cum_weights lève une
TypeError
.Les weights ou cum_weights peuvent utiliser n'importe quel type numérique interopérable avec les valeurs
float
renvoyées parrandom()
(qui inclut les entiers, les flottants et les fractions mais exclut les décimaux). Les poids sont présumés être non négatifs et finis. Une exceptionValueError
est levée si tous les poids sont à zéro.For a given seed, the
choices()
function with equal weighting typically produces a different sequence than repeated calls tochoice()
. The algorithm used bychoices()
uses floating-point arithmetic for internal consistency and speed. The algorithm used bychoice()
defaults to integer arithmetic with repeated selections to avoid small biases from round-off error.Ajouté dans la version 3.6.
Modifié dans la version 3.9: Lève une
ValueError
si tous les poids sont à zéro.
- random.shuffle(x)¶
Mélange la séquence x sans créer de nouvelle instance (« sur place »).
Pour mélanger une séquence immuable et renvoyer une nouvelle liste mélangée, utilisez
sample(x, k=len(x))
à la place.Notez que même pour les petits
len(x)
, le nombre total de permutations de x peut rapidement devenir plus grand que la période de la plupart des générateurs de nombres aléatoires. Cela implique que la plupart des permutations d'une longue séquence ne peuvent jamais être générées. Par exemple, une séquence de longueur 2080 est la plus grande qui puisse tenir dans la période du générateur de nombres aléatoires Mersenne Twister.Modifié dans la version 3.11: Removed the optional parameter random.
- random.sample(population, k, *, counts=None)¶
Return a k length list of unique elements chosen from the population sequence. Used for random sampling without replacement.
Renvoie une nouvelle liste contenant des éléments de la population tout en laissant la population originale inchangée. La liste résultante est classée par ordre de sélection de sorte que toutes les sous-tranches soient également des échantillons aléatoires valides. Cela permet aux gagnants du tirage (l'échantillon) d'être divisés en gagnants du grand prix et en gagnants de la deuxième place (les sous-tranches).
Les membres de la population n'ont pas besoin d'être hachables ou uniques. Si la population contient des répétitions, alors chaque occurrence est un tirage possible dans l'échantillon.
Les éléments répétés peuvent être spécifiés un à la fois ou avec le paramètre optionnel uniquement nommé counts. Par exemple,
sample([‘red’, ‘blue’], counts=[4, 2], k=5)
est équivalent àsample([‘red’, ‘red’, ‘red’, ‘red’, ‘blue’, ‘blue’], k=5)
.Pour choisir un échantillon parmi un intervalle d'entiers, utilisez un objet
range()
comme argument. Ceci est particulièrement rapide et économe en mémoire pour un tirage dans une grande population :échantillon(range(10000000), k=60)
.Si la taille de l'échantillon est supérieure à la taille de la population, une
ValueError
est levée.Modifié dans la version 3.9: Ajoute le paramètre counts.
Modifié dans la version 3.11: The population must be a sequence. Automatic conversion of sets to lists is no longer supported.
Discrete distributions¶
The following function generates a discrete distribution.
- random.binomialvariate(n=1, p=0.5)¶
Binomial distribution. Return the number of successes for n independent trials with the probability of success in each trial being p:
Mathematically equivalent to:
sum(random() < p for i in range(n))
The number of trials n should be a non-negative integer. The probability of success p should be between
0.0 <= p <= 1.0
. The result is an integer in the range0 <= X <= n
.Ajouté dans la version 3.12.
Distributions pour les nombres réels¶
Les fonctions suivantes génèrent des distributions spécifiques en nombre réels. Les paramètres de fonction sont nommés d'après les variables correspondantes de l'équation de la distribution, telles qu'elles sont utilisées dans la pratique mathématique courante ; la plupart de ces équations peuvent être trouvées dans tout document traitant de statistiques.
- random.random()¶
Return the next random floating-point number in the range
0.0 <= X < 1.0
- random.uniform(a, b)¶
Return a random floating-point number N such that
a <= N <= b
fora <= b
andb <= N <= a
forb < a
.The end-point value
b
may or may not be included in the range depending on floating-point rounding in the expressiona + (b-a) * random()
.
- random.triangular(low, high, mode)¶
Return a random floating-point number N such that
low <= N <= high
and with the specified mode between those bounds. The low and high bounds default to zero and one. The mode argument defaults to the midpoint between the bounds, giving a symmetric distribution.
- random.betavariate(alpha, beta)¶
Distribution bêta. Les conditions sur les paramètres sont
alpha > 0
etbeta > 0
. Les valeurs renvoyées varient entre 0 et 1.
- random.expovariate(lambd=1.0)¶
Distribution exponentielle. lambd est 1,0 divisé par la moyenne désirée. Ce ne doit pas être zéro. (Le paramètre aurait dû s'appeler "lambda", mais c'est un mot réservé en Python.) Les valeurs renvoyées vont de 0 à plus l'infini positif si lambd est positif, et de moins l'infini à 0 si lambd est négatif.
Modifié dans la version 3.12: Added the default value for
lambd
.
- random.gammavariate(alpha, beta)¶
Gamma distribution. (Not the gamma function!) The shape and scale parameters, alpha and beta, must have positive values. (Calling conventions vary and some sources define 'beta' as the inverse of the scale).
La fonction de distribution de probabilité est :
x ** (alpha - 1) * math.exp(-x / beta) pdf(x) = -------------------------------------- math.gamma(alpha) * beta ** alpha
- random.gauss(mu=0.0, sigma=1.0)¶
Normal distribution, also called the Gaussian distribution. mu is the mean, and sigma is the standard deviation. This is slightly faster than the
normalvariate()
function defined below.Note sur les fils d’exécution multiples (Multithreading) : quand deux fils d’exécution appellent cette fonction simultanément, il est possible qu’ils reçoivent la même valeur de retour. On peut l’éviter de 3 façons. 1) Avoir chaque fil utilisant une instance différente du générateur de nombres aléatoires. 2) Mettre des verrous autour de tous les appels. 3) Utiliser la fonction plus lente, mais compatible avec les programmes à fils d’exécution multiples,
normalvariate()
à la place.Modifié dans la version 3.11: mu and sigma now have default arguments.
- random.lognormvariate(mu, sigma)¶
Logarithme de la distribution normale. Si vous prenez le logarithme naturel de cette distribution, vous obtiendrez une distribution normale avec mu moyen et écart-type sigma. mu peut avoir n'importe quelle valeur et sigma doit être supérieur à zéro.
- random.normalvariate(mu=0.0, sigma=1.0)¶
Distribution normale. mu est la moyenne et sigma est l'écart type.
Modifié dans la version 3.11: mu and sigma now have default arguments.
- random.vonmisesvariate(mu, kappa)¶
mu est l'angle moyen, exprimé en radians entre 0 et 2*pi, et kappa est le paramètre de concentration, qui doit être supérieur ou égal à zéro. Si kappa est égal à zéro, cette distribution se réduit à un angle aléatoire uniforme sur la plage de 0 à 2*pi.
- random.paretovariate(alpha)¶
Distribution de Pareto. alpha est le paramètre de forme.
- random.weibullvariate(alpha, beta)¶
Distribution de Weibull. alpha est le paramètre de l'échelle et beta est le paramètre de forme.
Générateur alternatif¶
- class random.Random([seed])¶
Classe qui implémente le générateur de nombres pseudo-aléatoires par défaut utilisé par le module
random
.Modifié dans la version 3.11: Formerly the seed could be any hashable object. Now it is limited to:
None
,int
,float
,str
,bytes
, orbytearray
.Subclasses of
Random
should override the following methods if they wish to make use of a different basic generator:- seed(a=None, version=2)¶
Override this method in subclasses to customise the
seed()
behaviour ofRandom
instances.
- getstate()¶
Override this method in subclasses to customise the
getstate()
behaviour ofRandom
instances.
- setstate(state)¶
Override this method in subclasses to customise the
setstate()
behaviour ofRandom
instances.
- random()¶
Override this method in subclasses to customise the
random()
behaviour ofRandom
instances.
Optionally, a custom generator subclass can also supply the following method:
- getrandbits(k)¶
Override this method in subclasses to customise the
getrandbits()
behaviour ofRandom
instances.
- class random.SystemRandom([seed])¶
Classe qui utilise la fonction
os.urandom()
pour générer des nombres aléatoires à partir de sources fournies par le système d'exploitation. Non disponible sur tous les systèmes. Ne repose pas sur un état purement logiciel et les séquences ne sont pas reproductibles. Par conséquent, la méthodeseed()
n'a aucun effet et est ignorée. Les méthodesgetstate()
etsetstate()
lèventNotImplementedError
si vous les appelez.
Remarques sur la reproductibilité¶
Sometimes it is useful to be able to reproduce the sequences given by a pseudo-random number generator. By reusing a seed value, the same sequence should be reproducible from run to run as long as multiple threads are not running.
La plupart des algorithmes et des fonctions de génération de graine du module aléatoire sont susceptibles d'être modifiés d'une version à l'autre de Python, mais deux aspects sont garantis de ne pas changer :
Si une nouvelle méthode de génération de graine est ajoutée, une fonction rétro-compatible sera offerte.
La méthode
random()
du générateur continuera à produire la même séquence lorsque la fonction de génération de graine compatible recevra la même semence.
Exemples¶
Exemples de base :
>>> random() # Random float: 0.0 <= x < 1.0
0.37444887175646646
>>> uniform(2.5, 10.0) # Random float: 2.5 <= x <= 10.0
3.1800146073117523
>>> expovariate(1 / 5) # Interval between arrivals averaging 5 seconds
5.148957571865031
>>> randrange(10) # Integer from 0 to 9 inclusive
7
>>> randrange(0, 101, 2) # Even integer from 0 to 100 inclusive
26
>>> choice(['win', 'lose', 'draw']) # Single random element from a sequence
'draw'
>>> deck = 'ace two three four'.split()
>>> shuffle(deck) # Shuffle a list
>>> deck
['four', 'two', 'ace', 'three']
>>> sample([10, 20, 30, 40, 50], k=4) # Four samples without replacement
[40, 10, 50, 30]
Simulations :
>>> # Six roulette wheel spins (weighted sampling with replacement)
>>> choices(['red', 'black', 'green'], [18, 18, 2], k=6)
['red', 'green', 'black', 'black', 'red', 'black']
>>> # Deal 20 cards without replacement from a deck
>>> # of 52 playing cards, and determine the proportion of cards
>>> # with a ten-value: ten, jack, queen, or king.
>>> deal = sample(['tens', 'low cards'], counts=[16, 36], k=20)
>>> deal.count('tens') / 20
0.15
>>> # Estimate the probability of getting 5 or more heads from 7 spins
>>> # of a biased coin that settles on heads 60% of the time.
>>> sum(binomialvariate(n=7, p=0.6) >= 5 for i in range(10_000)) / 10_000
0.4169
>>> # Probability of the median of 5 samples being in middle two quartiles
>>> def trial():
... return 2_500 <= sorted(choices(range(10_000), k=5))[2] < 7_500
...
>>> sum(trial() for i in range(10_000)) / 10_000
0.7958
Exemple de *bootstrapping* statistique utilisant le ré-échantillonnage avec remise pour estimer un intervalle de confiance pour la moyenne d'un échantillon :
# https://www.thoughtco.com/example-of-bootstrapping-3126155
from statistics import fmean as mean
from random import choices
data = [41, 50, 29, 37, 81, 30, 73, 63, 20, 35, 68, 22, 60, 31, 95]
means = sorted(mean(choices(data, k=len(data))) for i in range(100))
print(f'The sample mean of {mean(data):.1f} has a 90% confidence '
f'interval from {means[5]:.1f} to {means[94]:.1f}')
Exemple d'un *resampling permutation test* pour déterminer la signification statistique ou valeur p d'une différence observée entre les effets d'un médicament et ceux d'un placebo :
# Example from "Statistics is Easy" by Dennis Shasha and Manda Wilson
from statistics import fmean as mean
from random import shuffle
drug = [54, 73, 53, 70, 73, 68, 52, 65, 65]
placebo = [54, 51, 58, 44, 55, 52, 42, 47, 58, 46]
observed_diff = mean(drug) - mean(placebo)
n = 10_000
count = 0
combined = drug + placebo
for i in range(n):
shuffle(combined)
new_diff = mean(combined[:len(drug)]) - mean(combined[len(drug):])
count += (new_diff >= observed_diff)
print(f'{n} label reshufflings produced only {count} instances with a difference')
print(f'at least as extreme as the observed difference of {observed_diff:.1f}.')
print(f'The one-sided p-value of {count / n:.4f} leads us to reject the null')
print(f'hypothesis that there is no difference between the drug and the placebo.')
Simulation des heures d'arrivée et des livraisons de services pour une file d'attente de serveurs :
from heapq import heapify, heapreplace
from random import expovariate, gauss
from statistics import mean, quantiles
average_arrival_interval = 5.6
average_service_time = 15.0
stdev_service_time = 3.5
num_servers = 3
waits = []
arrival_time = 0.0
servers = [0.0] * num_servers # time when each server becomes available
heapify(servers)
for i in range(1_000_000):
arrival_time += expovariate(1.0 / average_arrival_interval)
next_server_available = servers[0]
wait = max(0.0, next_server_available - arrival_time)
waits.append(wait)
service_duration = max(0.0, gauss(average_service_time, stdev_service_time))
service_completed = arrival_time + wait + service_duration
heapreplace(servers, service_completed)
print(f'Mean wait: {mean(waits):.1f} Max wait: {max(waits):.1f}')
print('Quartiles:', [round(q, 1) for q in quantiles(waits)])
Voir aussi
Statistics for Hackers un tutoriel vidéo par Jake Vanderplas sur l'analyse statistique en utilisant seulement quelques concepts fondamentaux dont la simulation, l'échantillonnage, le brassage et la validation croisée.
Economics Simulation a simulation of a marketplace by Peter Norvig that shows effective use of many of the tools and distributions provided by this module (gauss, uniform, sample, betavariate, choice, triangular, and randrange).
A Concrete Introduction to Probability (using Python) a tutorial by Peter Norvig covering the basics of probability theory, how to write simulations, and how to perform data analysis using Python.
Cas pratiques¶
These recipes show how to efficiently make random selections
from the combinatoric iterators in the itertools
module:
def random_product(*args, repeat=1):
"Random selection from itertools.product(*args, **kwds)"
pools = [tuple(pool) for pool in args] * repeat
return tuple(map(random.choice, pools))
def random_permutation(iterable, r=None):
"Random selection from itertools.permutations(iterable, r)"
pool = tuple(iterable)
r = len(pool) if r is None else r
return tuple(random.sample(pool, r))
def random_combination(iterable, r):
"Random selection from itertools.combinations(iterable, r)"
pool = tuple(iterable)
n = len(pool)
indices = sorted(random.sample(range(n), r))
return tuple(pool[i] for i in indices)
def random_combination_with_replacement(iterable, r):
"Choose r elements with replacement. Order the result to match the iterable."
# Result will be in set(itertools.combinations_with_replacement(iterable, r)).
pool = tuple(iterable)
n = len(pool)
indices = sorted(random.choices(range(n), k=r))
return tuple(pool[i] for i in indices)
Par défaut random()
renvoie des multiples de 2⁻⁵³ dans la plage 0.0 ≤ x < 1.0. Tous ces nombres sont uniformément répartis et sont représentés exactement en tant que nombre à virgule flottante Python. Cependant, de nombreux autres nombres à virgule flottante dans cette plage, et représentables en Python, ne sont pas sélectionnables. Par exemple 0.05954861408025609
n’est pas un multiple de 2⁻⁵³.
La recette suivante utilise une approche différente. Tous les nombres à virgule flottante de l’intervalle sont sélectionnables. La mantisse provient d’une distribution uniforme d’entiers dans la plage 2⁵² ≤ mantisse < 2⁵³. L’exposant provient d’une distribution géométrique où les exposants plus petits que -53 apparaissent moitié moins souvent que l’exposant suivant juste plus grand.
from random import Random
from math import ldexp
class FullRandom(Random):
def random(self):
mantissa = 0x10_0000_0000_0000 | self.getrandbits(52)
exponent = -53
x = 0
while not x:
x = self.getrandbits(32)
exponent += x.bit_length() - 32
return ldexp(mantissa, exponent)
Toutes les real valued distributions dans la classe seront utilisées dans la nouvelle méthode :
>>> fr = FullRandom()
>>> fr.random()
0.05954861408025609
>>> fr.expovariate(0.25)
8.87925541791544
La recette est conceptuellement équivalente à un algorithme qui choisit parmi tous les multiples de 2⁻¹⁰⁷⁴ dans la plage 0.0 ≤ x < 1.0. Tous ces nombres sont uniformément répartis, mais la plupart doivent être arrondis au nombre à virgule Python inférieur. (La valeur 2⁻¹⁰⁷⁴ est le plus petit nombre à virgule flottante positif et est égal à math.ulp(0.0)
.)
Voir aussi
Generating Pseudo-random Floating-Point Values une publication par Allen B. Downey décrivant des manières de générer des nombres à virgule flottante plus fins que normalement générés par random()
.