【发布时间】:2013-05-30 05:09:20
【问题描述】:
当使用 Array#shuffle 时,Ruby 允许使用自定义随机化器,甚至提供类 Random 来使用它。以下示例使用种子值为 48 的类。
array = [1,2,3,4,5,6,7,8,9,10]
array.shuffle(random: Random.new(48)) # => [8,6,3,7,10,9,5,2,4,1]
我写了一个小单位测试,看看有多少次一个值首先出现在打乱的数组中。
deck = (1..10).to_a
counts = Hash.new(0)
rng = Random.new
50000.times do
counts[deck.shuffle(random: rng).first] += 1
end
1.upto(10) do |card|
puts "#{card}:\t#{counts[card]}"
end
输出类似于以下内容:
1: 4942
2: 5100
3: 4938
4: 4960
5: 5024
6: 4992
7: 5184
8: 4930
9: 4916
10: 5014
假设我想用一个新类替换伪随机数生成器。由于 Array#shuffle 在上面的示例中似乎使用了 Random#rand,因此实现一个新类作为随机播放的 RNG 似乎很简单。在这里,我实现了一个新的伪随机数生成器,它实际上只是 rand 的一个非常简单的包装器:
deck = (1..10).to_a
counts = Hash.new(0)
class FooRandom
def rand(max=nil)
max.nil? ? Kernel::rand : Kernel::rand(max)
end
end
rng = FooRandom.new
50000.times do
counts[deck.shuffle(random: rng).first] += 1
end
1.upto(10) do |card|
puts "#{card}:\t#{counts[card]}"
end
但是,这并没有按预期运行。 FooRandom#rand 被调用,但改组产生以下分布:
1: 0
2: 5423
3: 5562
4: 5544
5: 5512
6: 5569
7: 5535
8: 5595
9: 5524
10: 5736
如你所见,数组洗牌后数组值 1 永远不会出现在数组的第一个位置。有人知道为什么吗?
【问题讨论】:
-
在 ruby-1.9.3-p392 中,我得到了两个示例的预期分布。但是在 Ruby-2.0.0-p0 中,我看到的结果和你一样。
-
谢谢你,肖恩。是的,我正在使用 ruby-2.0.0-p0。
标签: ruby