随机几乎没有随意?

时间:2010-01-27 08:50:52

标签: python random birthday-paradox

我这样做是为了测试randint的随机性:

>>> from random import randint
>>>
>>> uniques = []
>>> for i in range(4500):  # You can see I was optimistic.
...     x = randint(500, 5000)
...     if x in uniques:
...         raise Exception('We duped %d at iteration number %d' % (x, i))
...     uniques.append(x)
...
Traceback (most recent call last):
  File "<stdin>", line 4, in <module>
Exception: We duped 887 at iteration number 7

我尝试了大约10倍以上,我得到的最好结果是在转发器之前迭代了121次。这是您从标准库中获得的最佳结果吗?

11 个答案:

答案 0 :(得分:275)

答案 1 :(得分:44)

在归咎于Python之前,你应该提高一些概率&amp;统计理论。首先阅读birthday paradox

顺便说一句,Python中的random模块使用Mersenne twister PRNG,它被认为是非常好的,具有巨大的周期并且经过了广泛的测试。所以请放心,你很好。

答案 2 :(得分:40)

如果您不想要重复序列,请生成顺序数组并使用random.shuffle

答案 3 :(得分:38)

作为对Nimbuz答案的回答:

http://xkcd.com/221/

alt text

答案 4 :(得分:15)

真正的随机性肯定包括在整个可能值集耗尽之前重复值。否则它不会是随机的,因为您可以预测值不会重复多长时间。

如果你掷过骰子,你肯定经常排成3个六分......

答案 5 :(得分:5)

答案 6 :(得分:4)

您正在4500范围内生成500 <= x <= 5000个随机数。然后检查每个数字是否已生成。 birthday problem告诉我们,如果n次尝试超出范围d,则其中两个数字匹配的概率是多少。

您还可以反转公式以计算在生成重复的可能性超过50%之前必须生成的数量。在这种情况下,>50%次迭代后您有79次机会找到重复的数字。

答案 7 :(得分:4)

那不是转发器。转发器是指重复相同的序列。不只是一个数字。

答案 8 :(得分:1)

您已经定义了4501个值(500-5000)的随机空间,并且您正在迭代4500次。你基本上保证在你写的测试中发生碰撞。

以另一种方式思考:

  • 当结果数组为空时P(重复)= 0
  • 数组P(重复)中的1个值= 1/4500
  • 数组P中的2个值(重复)= 2/4500

因此,到达45/4500时,该插入有1%的可能性是重复,并且随着每个后续插入,该概率会不断增加。

要创建真正测试随机函数能力的测试,请增加可能随机值的范围(例如:500-500000)您可能会,也可能不会获得欺骗。但是你平均会得到更多的迭代。

答案 9 :(得分:0)

对于有此问题的其他人,我使用了uuid.uuid4(),它就像一个魅力。

答案 10 :(得分:0)

有生日悖论。考虑到这一点,你意识到你所说的是找到“764,3875,4290,4378,764”或类似的东西并不是随机的,因为该序列中的数字会重复。真正的方法是将序列相互比较。我写了一个python脚本来做这件事。

from random import randint
y = 21533456
uniques = []
for i in range(y):  
    x1 = str(randint(500, 5000))
    x2 = str(randint(500, 5000))
    x3 = str(randint(500, 5000))
    x4 = str(randint(500, 5000))
    x = (x1 + ", " + x2 + ", " + x3 + ", " + x4)
if x in uniques:
    raise Exception('We duped the sequence %d at iteration number %d' % (x, i))
else:
    raise Exception('Couldn\'t find a repeating sequence in %d iterations' % (y))
uniques.append(x)