在Python中创建随机整数列表


71

我想创建一个随机的整数列表以进行测试。数字的分布并不重要。唯一要数的是时间。我知道生成随机数是一项耗时的任务,但是必须有更好的方法。

这是我当前的解决方案:

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

v2比v1快,但无法大规模运行。它给出以下错误:

ValueError:样本大于总体

是否有一个快速,有效的解决方案能够在这种规模上工作?

答案的一些结果

安德鲁的:0.000290962934494

咬人:0.0058455221653

肯尼TM:0.00219276118279

NumPy来了,看到了,并被征服了。


4
当然不行了。random.sample()耗尽了人口,使数字越来越不随机。一旦整个人口都枯竭,就不可能进一步取样。
伊格纳西奥·巴斯克斯

当您说这是出于测试目的时,测试需要多长时间?
Mike Dunlavey 2010年

对于需要时间(但不需要加密和安全性)的仿真,则通常使用线性同余生成器(LCG)。我相信Mersenne Twister速度快(但比LCG慢),并且如果我没记错的话,它可以提供均匀的分布。
jww

Answers:


61

尚不清楚您想要什么,但是我将使用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

这给了我的机器:

0.0233682730198
0.00781716918945
0.000147947072983

请注意,randint与random.sample有很大不同(为了使它能在您的情况下工作,我必须将1000更改为10,000,正如一位评论员指出的那样-如果您确实希望将它们从0更改为1,000,则可以除以10)。

如果您真的不在乎所获得的分布情况,那么您可能不太了解问题或随机数-如果听起来很不礼貌,请您道歉...


3
numpy +1,如果Stiggo需要这么多随机数,则可能值得为此安装numpy
John La Rooy 2010年

安德鲁,关于发行,您绝对正确。但这不是真实的事情。朋友之间的挑战。:D干杯!
Stiggo,2010年

31

所有随机方法最终都会调用,random.random()因此最好的方法是直接调用它:

[int(1000*random.random()) for i in xrange(10000)]

例如,

  • random.randint来电random.randrange
  • random.randrange返回前有一堆开销要检查范围istart + istep*int(self.random() * n)

NumPy当然要快得多。


+1我只是在较早地进行了研究,最后想到了randrange最终导致了对的呼叫getrandbits。我想念您必须实例化SystemRandom该行为。感谢您让我看起来更近。
aaronasterling

1
@Stiggo,可以肯定,我认为不使用numpy的唯一原因是您的平台上不支持numpy。例如。google app引擎
John La Rooy

4
在Python3中,random.randrange(1000)设计为产生比random.random()* 1000更均匀的分布。请参阅此处的9.6.2节:docs.python.org/3/library/random.html
Alexey

1
@AlexeyPolonsky,不错的接送。如果我们高兴地将数字增加到1023,则[getrandbits(10) for r in range(10000)]比我的答案中列表理解的速度快9倍
John La Rooy

1
@JohnLaRooy谢谢!这实际上甚至更有用!
Alexey Polonsky

6

您对性能的问题没有任何意义-两种功能都非常快。你的代码的速度由你什么来决定与随机数。

但是,了解这两个功能在行为上的区别很重要。一种是随机抽样替换,另一种是随机抽样替换。


3

首先,您应该使用randrange(0,1000)randint(0,999),而不是randint(0,1000)。的上限randint(包括)。

为了高效randint起见,randrangerandom只是调用的包装,因此您应该使用random。另外,xrange请将用作参数sample,而不是range

你可以用

[a for a in sample(xrange(1000),1000) for _ in range(10000/1000)]

使用sample10次生成10,000个范围内的数字。

(当然,这不会击败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

但是,由于您不关心数字的分布,所以为什么不使用:

range(1000)*(10000/1000)


randrange(1000)花费的时间是1000*int(random())我电脑上的两倍多
John La Rooy

目的是10000/1000什么?
彼得·莫滕森
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.