Pythons是random.randint统计随机吗?

时间:2012-08-28 17:16:48

标签: python random statistics probability

所以我正在测试计算游戏的某些骰子掷骰的概率。 如果那个滚动的10面死的基本情况。

我做了一百万个这样的样本,结果是以下比例:

Result
0       0.000000000000000%
1       10.038789961210000%
2       10.043589956410000%
3       9.994890005110000%
4       10.025289974710000%
5       9.948090051909950%
6       9.965590034409970%
7       9.990190009809990%
8       9.985490014509990%
9       9.980390019609980%
10      10.027589972410000%

这些当然应该都是10%。 这些结果的标准偏差为0.0323207%。 对我来说,这似乎相当高。 这只是巧合吗? 据我了解,随机模块访问适当的伪随机数。 即通过统计测试的方法是随机的。 或者是这些伪伪随机数生成器

我应该使用加密伪随机数生成器吗? 我很确定我不需要 true 随机数生成器(参见http://www.random.org/http://en.wikipedia.org/wiki/Hardware_random_number_generator)。

我目前用10亿个样本重新生成所有结果, (为什么不呢,我有一个松脆的服务器供我使用,还有一些睡觉要做)

6 个答案:

答案 0 :(得分:15)

来自random module documentation

  

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

来自Wikipedia article on the Mersenne Twister

  

它提供了快速生成非常高质量的伪随机数,专门用于纠正旧算法中的许多缺陷。

如果您有可通过os.urandom()获得的特定于操作系统的随机源,则可以使用random.SystemRandom()类。大多数random模块函数都可以作为该类的方法使用。它可能更适合加密目的,再次引用文档:

  

对于加密应用程序,返回的数据应该是不可预测的,尽管它的确切质量取决于操作系统的实现。

Python 3.6添加了一个带有便捷方法的secrets module来生成适合加密目的的随机数据:

  

secrets模块用于生成适用于管理密码,帐户身份验证,安全令牌和相关机密等数据的加密强随机数。

     

特别是,secrets应优先于random模块中的默认伪随机数生成器使用,该模块专为建模和模拟而设计,而非安全性或加密。

答案 1 :(得分:3)

我以10亿次迭代重申OP的练习:

from collections import Counter
import random
n = 1000000000
c = Counter(random.randint(1, 10) for _ in xrange(n))
for i in range(1,11):
    print '%2s  %02.10f%%' % (i, c[i] * 100.0 / n)

这是(重新格式化)的结果:

 1     9.9996500000%
 2    10.0011089000%
 3    10.0008568000%
 4    10.0007495000%
 5     9.9999089000%
 6     9.9985344000%
 7     9.9994913000%
 8     9.9997877000%
 9    10.0010818000%
10     9.9988307000%

请参阅此问题的其他答案,以获得出色的分析。

答案 2 :(得分:2)

是的,对于所有实际目的而言,它在统计上是随机的。你看到的随机变化是完全正常的。事实上,如果它没有这样的变化,那将是一个糟糕的。

由于prng的周期是2 ** 19937-1,因此在看到非随机分布之前,您需要生成比宇宙中的原子更多的数字。请注意,如果生成623维向量,则它会更快地变为非随机。

答案 3 :(得分:2)

Martijn的回答是对Python可以访问的随机数生成器的简洁回顾。

如果要查看生成的伪随机数据的属性,请从http://www.fourmilab.ch/random/下载random.zip,然后在大量随机数据样本上运行它。特别是χ²(卡方检验)检验对随机性非常敏感。对于一个非常随机的序列,χ²检验的百分比应在10%到90%之间。

对于一款游戏,我猜测Python内部使用的Mersenne Twister应该是随机的(除非你正在建立一个在线赌场: - )。

如果您想要随机性,并且如果您使用的是Linux,则可以阅读/dev/random。这只会从内核的熵池(从中断到达的不可预测的时间收集)中产生随机数据,因此如果你耗尽它就会阻塞它。该熵用于初始化(种子)/dev/urandom使用的PRNG。在FreeBSD上,为/dev/random提供数据的PRNG使用Yarrow算法,该算法通常被认为是加密安全的。

编辑:我对来自random.randint的字节进行了一些测试。首先创建一百万个随机字节:

import random
ba = bytearray([random.randint(0,255) for n in xrange(1000000)])
with open('randint.dat', 'w+') as f:
    f.write(ba)

然后我在Fourmilab上运行了ent程序:

Entropy = 7.999840 bits per byte.

Optimum compression would reduce the size
of this 1000000 byte file by 0 percent.

Chi square distribution for 1000000 samples is 221.87, and randomly
would exceed this value 93.40 percent of the times.

Arithmetic mean value of data bytes is 127.5136 (127.5 = random).
Monte Carlo value for Pi is 3.139644559 (error 0.06 percent).
Serial correlation coefficient is -0.000931 (totally uncorrelated = 0.0).

现在对于χ²测试,你从50%得到的越远,数据越可疑。如果一个人非常挑剔,则值<10%或> 90%被认为是不可接受的。 ent的作者约翰沃克称此值“几乎可疑”。

作为对比,以下是我之前运行的FreeBSD的Yarrow prng对10 MiB的分析:

Entropy = 7.999982 bits per byte.

Optimum compression would reduce the size
of this 10485760 byte file by 0 percent.

Chi square distribution for 10485760 samples is 259.03, and randomly
would exceed this value 41.80 percent of the times.

Arithmetic mean value of data bytes is 127.5116 (127.5 = random).
Monte Carlo value for Pi is 3.139877754 (error 0.05 percent).
Serial correlation coefficient is -0.000296 (totally uncorrelated = 0.0).

虽然其他数据似乎没有太大差异,但χ²的百分比很多接近50%。

答案 4 :(得分:1)

随着PRNG的良好分布,随机数的出现确实是正常的。但是,您生成的数字越多,您应该看到的数字越少。

顺便说一句,我得到的标准差为0.03066,略低于你给出的标准差。

答案 5 :(得分:0)

这些结果与您期望的结果非常接近,您可以通过简单的计算来检查。如果您滚动1,000,000 D10并计算1的数量(比方说),该随机变量的平均值为100,000(试验次数*成功概率),方差为90,000(试验次数*成功概率*失败概率),所以标准差是sqrt(90,000)= 300。所以你应该期望从100,000到300左右,即10%+ / - 0.03%。