【发布时间】:2017-10-03 22:22:48
【问题描述】:
这是我目前正在使用的生成器:
from random import Random
def shuffle(size):
"""Yield random items from range(size) without replacement."""
pool = list(range(size))
rng = Random()
while pool:
yield pool.pop(rng.randrange(len(pool)))
当我使用这个生成器时,它的随机性似乎没有那么大。例如,前 4 项通常都出现在结果的前半部分或后半部分。
我正在考虑进行此更改:
def shuffle(size):
"""Yield random items from range(size) without replacement."""
pool = list(range(size))
rng = Random()
while pool:
i = rng.randrange(len(pool))
yield pool[i]
pool[i] = pool[-1]
del pool[-1]
这类似于random.sample(第 326 行)所做的事情。我不知道这是为了速度还是因为它在不牺牲速度的情况下让它更加随机。
为了简单起见,我更喜欢第一个示例,但第二个示例更加复杂,我不知道 PRNG 是否符合真正的随机性。有没有办法证明第二个例子是否更随机,也许是通过引用 Mersenne Twister 算法(Python 使用的)的弱点?
如果无法以一种或另一种方式证明任何事情,我将如何测试这两种算法的随机性?我知道我需要编写一个包含许多试验的测试,但我不知道如何分析结果。
我不想使用random.sample,因为我希望我的最终列表是部分排序的,我认为生成器会更好。
【问题讨论】:
-
“例如,前 4 项通常都出现在结果的前半部分或后半部分”——这是完全正常的。
-
第一个版本很好。你的第二个版本除了浪费时间什么都没做。不,你所做的任何事情都不可能对直接使用 MT 有所改善,而且你很可能会使情况变得更糟。不要滚动你自己的加密货币,也不要滚动你自己的 RNG,除非你是一个严肃的数学极客。
-
编辑澄清我为什么考虑第二个版本。我不是想推出自己的 RNG。