9.6. random - 生成伪随机数字

源代码: Lib / random.py

这个模块实现了对各种分布的伪随机数发生器。

对于整数,有一个范围的均匀选择。对于序列,存在随机元素的均匀选择,产生就地列表的随机置换的函数,以及用于无替换的随机采样的函数。

实际上,存在计算均匀,正态(高斯),对数正态,负指数,伽马和β分布的函数。为了生成角度分布,可以使用von Mises分布。

几乎所有模块函数都依赖于基本函数random(),其在半开放范围[0.0,1.0)中均匀地生成随机浮点数。Python使用Mersenne Twister作为核心生成器。它产生53位精确度浮点数,周期为2 ** 19937-1。C中的底层实现既快又线程安全。Mersenne Twister是现存最广泛测试的随机数生成器之一。然而,完全确定性,它不适合于所有目的,并且完全不适合于加密目的。

该模块提供的函数实际上是random.Random类的隐藏实例的约束方法。您可以实例化您自己的Random实例,以获得不共享状态的生成器。

如果你想使用你自己设计的不同的基本生成器,类Random也可以是子类:在这种情况下,覆盖random()seed()getstate()setstate()方法。可选地,新的生成器可以提供getrandbits()方法 - 这允许randrange()在任意大的范围上产生选择。

random模块还提供SystemRandom类,它使用系统函数os.urandom()从操作系统提供的源生成随机数。

警告

该模块的伪随机生成器不应该用于安全目的。

记账功能:

random.seed(a=None, version=2)

初始化生成器的随机数。

如果省略aNone,则使用当前系统时间。如果随机源由操作系统提供,则使用它们而不是系统时间(有关可用性的详细信息,请参阅os.urandom()函数)。

如果a是一个int,它直接使用。

对于版本2(默认值),strbytesbytearray对象将转换为int使用其所有位。在版本1中,使用ahash()

在版本3.2中更改:移动到使用字符串种子中的所有位的版本2方案。

random.getstate()

返回捕获生成器的当前内部状态的对象。此对象可以传递到setstate()以恢复状态。

random.setstate(state)

状态应该从先前对getstate()的调用获得,并且setstate()将生成器的内部状态恢复为是在当时getstate()被调用。

random.getrandbits(k)

返回一个 k 位(bit) 的随机整数(译者注:如k=8,返回8bit范围内的随机数,即0-255的随机数)该方法与MersenneTwister生成器一起提供,并且一些其他生成器也可以将其提供为API的可选部分。当可用时,getrandbits()启用randrange()以处理任意大的范围。

整数的函数:

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

range(start, stop, step)返回一个start到end范围内的随机整数(译者注:start,end,step都是整数,不包含end),可以指定step。这等同于选择(范围(开始, 停止, 步骤)) 范围对象。

位置参数模式与range()匹配。不应使用关键字参数,因为函数可能以意想不到的方式使用它们。

在版本3.2中更改: randrange()更复杂地生成平均分布的值。以前,它使用类似int(random()*n)这样可能产生轻微的不均匀分布。

random.randint(a, b)

返回随机整数N以使得a N / t5> brandrange(a, b + 1)的别名。

序列函数:

random.choice(seq)

从非空序列seq返回一个随机元素。如果seq为空,则引发IndexError

random.shuffle(x[, random])

随机播放序列x可选参数random是返回[0.0,1.0)中的随机浮点的0参数函数;默认情况下,这是函数random()

注意,对于甚至相当小的len(x)x的排列的总数大于大多数随机数生成器的周期;这意味着长序列的大多数排列永远不会生成。

random.sample(population, k)

返回从群体序列或集合中选择的唯一元素的k长度列表。用于随机抽样,无需更换。

返回包含来自总体的元素的新列表,而保持原始填充值不变。结果列表以选择顺序,使得所有子片段也将是有效的随机样本。这允许抽奖获奖者(样本)被分成大奖和第二名获奖者(子分类)。

群体的成员不需要hashable或唯一的。如果群体包含重复,则每次出现是样品中的可能选择。

要从整数范围中选择样本,请使用range()对象作为参数。这对于从大群体采样是特别快速和节省空间的:sample(range(10000000), 60)

如果样本大小大于总体大小,则会引发ValueError

以下函数生成特定的实值分布。函数参数以分布方程中的相应变量命名,如在常见的数学实践中使用的;大多数这些方程可以在任何统计文本中找到。

random.random()

返回下一个在范围 [0.0, 1.0) 中的随机浮点数。

random.uniform(a, b)

Return a random floating point number N such that a <= N <= b for a <= b and b <= N <= a for b < a.

根据等式a +中的浮点舍入,端点值b (ba) * random()

random.triangular(low, high, mode)

返回随机浮点数N,使得 N = ,并指定模式边界默认为零和一。模式参数默认为边界之间的中点,给出对称分布。

random.betavariate(alpha, beta)

Beta分布。Conditions on the parameters are alpha > 0 and beta > 0. 返回值的范围为0到1。

random.expovariate(lambd)

指数分布。lambd为1.0除以所需平均值。它应该是非零的。(该参数将被称为“lambda”,但这是Python中的保留字。)如果lambd为正,返回值的范围为0到正无穷大,如果lambd为负,则从负无穷大到0。

random.gammavariate(alpha, beta)

伽玛分布。伽玛函数!)Conditions on the parameters are alpha > 0 and beta > 0.

概率分布函数为:

          x ** (alpha - 1) * math.exp(-x / beta)
pdf(x) =  --------------------------------------
            math.gamma(alpha) * beta ** alpha
random.gauss(mu, sigma)

高斯分布。mu是平均值,sigma是标准偏差。这稍微快于下面定义的normalvariate()函数。

random.lognormvariate(mu, sigma)

对数正态分布。如果采用此分布的自然对数,您将得到平均值mu和标准偏差sigma的正态分布。mu可以具有任何值,并且sigma必须大于零。

random.normalvariate(mu, sigma)

正态分布。mu是平均值,sigma是标准偏差。

random.vonmisesvariate(mu, kappa)

mu is the mean angle, expressed in radians between 0 and 2*pi, and kappa is the concentration parameter, which must be greater than or equal to zero. If kappa is equal to zero, this distribution reduces to a uniform random angle over the range 0 to 2*pi.

random.paretovariate(alpha)

帕累托分布。alpha是形状参数。

random.weibullvariate(alpha, beta)

Weibull分布。alpha是缩放参数,beta是形状参数。

替代生成器:

class random.SystemRandom([seed])

使用os.urandom()函数从操作系统提供的源生成随机数的类。不适用于所有系统。不依赖于软件状态,序列不可重现。因此,seed()方法没有效果,并被忽略。如果调用getstate()setstate()方法引发NotImplementedError

也可以看看

M. Matsumoto和T.Nishimura,“Mersenne Twister:A 623-dimensionalionally equidistributed uniform pseudorandom number生成器”,ACM Transactions on Modeling and Computer Simulation Vol。8,No.1,January pp.3-30 1998。

互补 - 乘法配方用于具有长期和相对简单的更新操作的兼容的替代随机数生成器。

9.6.1.重现性注释

有时,能够再现由伪随机数生成器给出的序列是有用的。通过重新使用种子值,只要多个线程不运行,相同的序列应该从运行重现到运行。

大多数随机模块的算法和种子函数可能会在Python版本中发生更改,但两个方面保证不会更改:

  • 如果添加新的播种方法,则将提供向后兼容的播种器。
  • 当兼容播种机被给予相同的种子时,生成器的random()方法将继续产生相同的序列。

9.6.2.示例和配方

基本用法:

>>> random.random()                      # Random float x, 0.0 <= x < 1.0
0.37444887175646646

>>> random.uniform(1, 10)                # Random float x, 1.0 <= x < 10.0
1.1800146073117523

>>> random.randrange(10)                 # Integer from 0 to 9
7

>>> random.randrange(0, 101, 2)          # Even integer from 0 to 100
26

>>> random.choice('abcdefghij')          # Single random element
'c'

>>> items = [1, 2, 3, 4, 5, 6, 7]
>>> random.shuffle(items)
>>> items
[7, 3, 2, 5, 6, 4, 1]

>>> random.sample([1, 2, 3, 4, 5],  3)   # Three samples without replacement
[4, 1, 5]

一个常见的任务是使用加权概率生成random.choice()

如果权重是小整数比,一个简单的技术是构建具有重复的样本总体:

>>> weighted_choices = [('Red', 3), ('Blue', 2), ('Yellow', 1), ('Green', 4)]
>>> population = [val for val, cnt in weighted_choices for i in range(cnt)]
>>> random.choice(population)
'Green'

更一般的方法是使用itertools.accumulate()在累积分布中排列权重,然后使用bisect.bisect()定位随机值:

>>> choices, weights = zip(*weighted_choices)
>>> cumdist = list(itertools.accumulate(weights))
>>> x = random.random() * cumdist[-1]
>>> choices[bisect.bisect(cumdist, x)]
'Blue'