Je voudrais créer une liste aléatoire de nombres entiers à des fins de test. La distribution des nombres n'est pas importante. La seule chose qui compte est time. Je sais que générer des nombres aléatoires est une tâche fastidieuse, mais il doit y avoir un meilleur moyen.
Voici ma solution actuelle:
import random
import timeit
# Random lists from [0-999] interval
print [random.randint(0, 1000) for r in xrange(10)] # v1
print [random.choice([i for i in xrange(1000)]) for r in xrange(10)] # v2
# Measurement:
t1 = timeit.Timer('[random.randint(0, 1000) for r in xrange(10000)]', 'import random') # v1
t2 = timeit.Timer('random.sample(range(1000), 10000)', 'import random') # v2
print t1.timeit(1000)/1000
print t2.timeit(1000)/1000
la v2 est plus rapide que la v1, mais elle ne fonctionne pas à une aussi grande échelle. Cela donne l'erreur suivante:
ValueError: échantillon supérieur à la population
Existe-t-il une solution rapide et efficace qui fonctionne à cette échelle?
Andrew's: 0.000290962934494
gnibbler: 0.0058455221653
KennyTM: 0.00219276118279
NumPy est venu, a vu et a conquis.
Ce que vous voulez n’est pas tout à fait clair, mais j’utiliserais numpy.random.randint :
import numpy.random as nprnd
import timeit
t1 = timeit.Timer('[random.randint(0, 1000) for r in xrange(10000)]', 'import random') # v1
### Change v2 so that it picks numbers in (0, 10000) and thus runs...
t2 = timeit.Timer('random.sample(range(10000), 10000)', 'import random') # v2
t3 = timeit.Timer('nprnd.randint(1000, size=10000)', 'import numpy.random as nprnd') # v3
print t1.timeit(1000)/1000
print t2.timeit(1000)/1000
print t3.timeit(1000)/1000
ce qui donne sur ma machine:
0.0233682730198
0.00781716918945
0.000147947072983
Notez que randint est très différent de random.sample (pour que cela fonctionne dans votre cas, je devais changer le nombre de 1 000 à 10 000 comme l'un des les commentateurs ont souligné - si vous les voulez vraiment de 0 à 1 000, vous pouvez les diviser par 10).
Et si vous ne vous souciez pas vraiment de la distribution que vous obtenez, il est possible que vous ne compreniez pas très bien votre problème, ou que vous choisissiez des nombres aléatoires - avec des excuses si cela vous semble impoli ...
Toutes les méthodes aléatoires finissent par appeler random.random()
. Le meilleur moyen est donc de l'appeler directement:
[int(1000*random.random()) for i in xrange(10000)]
Par exemple,
random.randint
Appelle random.randrange
.random.randrange
A un tas de temps système pour vérifier la plage avant de renvoyer istart + istep*int(self.random() * n)
.NumPy est bien plus rapide encore.
Votre question sur les performances est sans objet. Les deux fonctions sont très rapides. La vitesse de votre code sera déterminée par ce que vous faites avec les nombres aléatoires.
Cependant, il est important que vous compreniez la différence entre comportement de ces deux fonctions. L'un effectue un échantillonnage aléatoire avec remplacement, l'autre effectue un échantillonnage aléatoire sans remplacement.
Tout d'abord, vous devez utiliser randrange(0,1000)
ou randint(0,999)
, pas randint(0,1000)
. La limite supérieure de randint
est inclusive.
Pour être efficace, randint
est simplement un wrapper de randrange
qui appelle random
, vous devez donc simplement utiliser random
. En outre, utilisez xrange
comme argument de sample
, et non de range
.
Vous pourriez utiliser
[a for a in sample(xrange(1000),1000) for _ in range(10000/1000)]
générer 10 000 nombres dans la plage en utilisant sample
10 fois.
(Bien sûr, cela ne battra pas NumPy.)
$ python2.7 -m timeit -s 'from random import randrange' '[randrange(1000) for _ in xrange(10000)]'
10 loops, best of 3: 26.1 msec per loop
$ python2.7 -m timeit -s 'from random import sample' '[a%1000 for a in sample(xrange(10000),10000)]'
100 loops, best of 3: 18.4 msec per loop
$ python2.7 -m timeit -s 'from random import random' '[int(1000*random()) for _ in xrange(10000)]'
100 loops, best of 3: 9.24 msec per loop
$ python2.7 -m timeit -s 'from random import sample' '[a for a in sample(xrange(1000),1000) for _ in range(10000/1000)]'
100 loops, best of 3: 3.79 msec per loop
$ python2.7 -m timeit -s 'from random import shuffle
> def samplefull(x):
> a = range(x)
> shuffle(a)
> return a' '[a for a in samplefull(1000) for _ in xrange(10000/1000)]'
100 loops, best of 3: 3.16 msec per loop
$ python2.7 -m timeit -s 'from numpy.random import randint' 'randint(1000, size=10000)'
1000 loops, best of 3: 363 usec per loop
Mais puisque vous ne vous souciez pas de la distribution des nombres, pourquoi ne pas simplement utiliser:
range(1000)*(10000/1000)
?