为什么我要为Array #shuffle使用自定义RNG?

时间:2015-07-14 07:20:16

标签: ruby random

Array#shuffle州的文档:

  

shuffle(random: rng) → new_ary

     

可选的rng参数将用作随机数生成器。

a.shuffle(random: Random.new(1))  #=> [1, 3, 2]

这是什么意思,我为什么要这样做?

2 个答案:

答案 0 :(得分:4)

可选的ContentPlaceHolder参数将创建一个固定的随机模式。

让我们在没有rng参数的情况下尝试shuffle,我们应该得到不同的随机模式:

rng

现在使用a = [ 1, 2, 3 ] a.shuffle # => [3, 2, 1] a.shuffle # => [2, 3, 1]

rng

正如您所看到的,混洗数组将始终包含相同的随机模式 - 在这种情况下为a.shuffle(random: Random.new(1)) # => [1, 3, 2] a.shuffle(random: Random.new(1)) # => [1, 3, 2]

我为什么要这样做?

如以下评论中所述

可重复随机非常有价值。它在测试,游戏等方面都很方便。

答案 1 :(得分:3)

Array#shuffle方法在内部需要随机数源。当您提供可选的RNG参数时,您告诉该方法使用该对象作为数据源。

直接用于再现性。默认情况下,.shuffle使用共享的Kernel#rand RNG,可以使用srand播种。

您可以按如下方式重现随机播放:

srand(30)
[0,1,2,3,4,5,6].shuffle
# => [3, 1, 2, 0, 4, 6, 5]

srand(30)
[0,1,2,3,4,5,6].shuffle
# => [3, 1, 2, 0, 4, 6, 5]

如果您只需要测试的可重复性,那么srand将满足您的需求。

那么是什么呢?

改组数组需要一个随机数源才能工作。通过允许您覆盖默认Kernel#rand,设计允许您控制这些来源的来源。需要随机源的其他功能也允许类似的过载,例如Array#sample

具有此级别的控制权允许您任意构建混洗数组,并与代码中依赖于随机数源的任何其他部分分开构建。可重复输出是一个有用的结果,使用可能需要或可能不需要可重复结果的随机数从程序的其他部分添加独立性,或者可能在您无法控制的不同时间运行。

此外,对于混洗算法,有a problem creating an even distribution when you have a long list。如果您正在洗牌N件,则需要factorial(N)或N!可能来自您的RNG的唯一数字列表,否则它不可能产生所有允许的安排。对于Ruby内置的RNG,当理论上对2000个项目进行混洗时会出现这个限制 - 前提是srand值是从高质量的原始随机源中选择的。你可以通过使用具有更高限制的RNG或者真正的"来做得更好。 RNG从物理系统中获取数据。