究竟是random.random做什么

时间:2009-12-25 15:36:32

标签: python random

    random.shuffle(lst_shuffle, random.random)

我知道后一部分是一个可选参数。但它究竟做了什么呢。我不明白这是什么意思。 这是来自文档。

  

random.random()¶   返回下一个随机浮点   数字在[0.0,1.0)范围内。

我也看到了这个,这个范围是0,0,1,0意味着什么?

Pseudorandom number generators
Most, if not all programming languages have libraries that include a pseudo-random
number generator. This generator usually returns a random number between 0 and 1 (not
including 1). In a perfect generator all numbers have the same probability of being selected but
in the pseudo generators some numbers have zero probability.

6 个答案:

答案 0 :(得分:5)

现有的答案很好地解决了具体的问题,但我认为值得一提的是一个侧面问题:为什么你特别想要将一个替代的“随机生成器”传递给shuffle而不是random模块中的其他功能。引用the docs

  

请注意,即使相当小   len(x),总数   x的排列大于   大多数随机数的时期   发电机;这意味着最多   长序列的排列可以   永远不会被生成。

短语“随机数生成器”在这里指的是可能更迂腐地称为 - 随机数生成器 - 生成器,它们可以很好地模仿随机性,但完全算法,因此是已知是“非常随机”。任何这样的算法方法都会有一个“周期” - 它最终会重新开始。

Python的random模块使用了一个特别好且经过充分研究的伪随机生成器Mersenne Twister,其周期为2**19937-1 - 一个数字超过6千位的数字当以十进制数字写出时,len(str(2**19937-1))将确认;-)。在我的笔记本电脑上,我每秒可以产生大约500万个这样的数字:

$ python -mtimeit -s'import random' 'random.random()'
1000000 loops, best of 3: 0.214 usec per loop

假设一台更快的机器,能够每秒生成十亿这样的数字,那么循环将需要大约10 5985 年来重复 - 以及最佳的当前估计因为宇宙的年龄略小于1.5 * 10 12 年。因此,几乎无法想象的宇宙生命周期达到重复的程度;-)。使计算并行不会有太大帮助;估计宇宙中大约有10个 80 原子,所以即使你能够在宇宙中的每个原子上运行这样一个每秒十亿次的发生器,它仍然需要超过10 5800 开始重复的宇宙生命。

所以,你可能有理由怀疑这种对重复的担心只是一个理论上的,而不是实际的问题; - )。

然而,阶乘(计算长度为N的序列的排列)也增长得相当快。例如,Mersenne Twister可能能够产生长度为2080的序列的所有排列,但绝对不能长度为2081或更高。如果不是“宇宙的一生”问题,文档对“即使是相当小的len(x)”的担心也是合理的 - 我们知道许多可能的排列永远无法达到一旦我们有一个相当长的序列,我们就会用这样一个伪RNG进行改组,所以人们可能会担心我们实际上会引入什么样的偏差甚至是一些shuffle!: - )

os.urandom调解对操作系统提供的物理随机性的任何来源的访问权限 - Windows上的CryptGenRandom,Linux上的/dev/urandom等等。{{1}给出了字节序列,但在struct的帮助下,很容易将它们变成随机的数字

os.urandom

现在我们可以致电>>> n = struct.calcsize('I') >>> def s2i(s): return struct.unpack('I', s)[0] ... >>> maxi = s2i(b'\xff'*n) + 1 >>> maxi = float(s2i(b'\xff'*n) + 1) >>> def rnd(): return s2i(os.urandom(n))/maxi 而不用担心偏见; - )。

不幸的是,测量显示这种RNG方法比调用random.shuffle(somelist, rnd)慢约50倍 - 如果我们需要很多随机数(如果我们不知道),这可能是一个重要的实际考虑因素。 t,对可能的偏见的担忧可能是错误的;-)。 random.random()方法也难以以可预测,可重复的方式使用(例如,用于测试目的),而使用os.urandom时,您只需在测试开始时提供固定的初始random.random()保证可重复的行为。

因此,在实践中,random.seed仅在您需要“加密质量”随机数 - 被确定的攻击者无法预测的随机数 - 并且因此愿意支付实际价格而不是使用它时使用os.urandom

答案 1 :(得分:4)

第二个参数用于指定要使用的随机数生成器。如果您需要/拥有比random.random“更好”的东西,这可能很有用。安全敏感的应用程序可能需要使用加密安全的随机数生成器。

random.randomrandom.random()之间的区别在于第一个是对产生简单随机数的函数的引用,第二个实际上是调用该函数。

如果您有另一个随机数生成器,您可以使用,您可以说

random.shuffle(x, my_random_number_function)

关于random.random(默认生成器)正在做什么,它使用一个名为Mersenne twister的算法来创建一个介于0和1(不包括1)之间的看似随机的浮点数,所有该区间内的数字具有相同的可能性。

间隔从0到1只是一种惯例。

答案 2 :(得分:1)

第二个参数是被调用以产生随机数的函数,而这些随机数又用于对序列进行混洗(第一个参数)。如果您不提供自己的默认函数,则使用random.random。

如果要自定义shuffle的执行方式,可能需要提供此参数。

您的自定义函数必须返回[0.0,1.0]范围内的数字 - 包含0.0,排除1.0。

答案 3 :(得分:0)

文档继续说:

  

随机可选参数是a   0参数函数返回一个随机的   漂浮在[0.0,1.0);默认情况下,这个   是函数random()。

这意味着您可以指定自己的随机数生成器函数,也可以告诉模块使用默认的random函数。第二个选项几乎总是最好的选择,因为Python使用了相当不错的PRNG。

它期望的函数应该返回[0.0,1.0]范围内的浮点伪随机数,这意味着包括0.0和1.0不包括(即0.9999是要返回的有效数字,但是1.0不是)。理论上应该以相同的概率返回该范围内的每个数字(即,这是线性分布)。

答案 4 :(得分:0)

shuffle函数取决于RNG(随机数生成器),默认为random.random。第二个参数是,所以你可以提供自己的RNG而不是默认值。

<强>更新

第二个参数是一个随机数生成器,每次调用它时都会生成[0.0,1.0]范围内的新随机数。

以下是您的示例:

import random

def a():
  return 0.0

def b():
  return 0.999999999999

arr = [1,2,3]

random.shuffle(arr)
print arr # prints [1, 3, 2]

arr.sort()
print arr # prints [1, 2, 3]

random.shuffle(arr)
print arr # prints [3, 2, 1]

arr.sort()
random.shuffle(arr, a)
print arr # prints [2, 3, 1]

arr.sort()
random.shuffle(arr, a)
print arr # prints [2, 3, 1]

arr.sort()
random.shuffle(arr, b)
print arr # prints [1, 2, 3]

arr.sort()
random.shuffle(arr, b)
print arr # prints [1, 2, 3]

因此,如果函数始终返回相同的值,则始终获得相同的排列。如果函数在每次调用时返回随机值,则会得到随机排列。

答案 5 :(得分:0)

来自example

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

它生成0到1之间的随机浮点数。