加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 百科 > 正文

使用Ruby Array #shuffle / sample的自定义随机数生成器

发布时间:2020-12-17 03:05:09 所属栏目:百科 来源:网络整理
导读:使用Array #shuffle时,Ruby允许使用自定义随机函数,甚至提供Random类来使用它.以下示例使用种子值为48的类. array = [1,2,3,4,5,6,7,8,9,10]array.shuffle(random: Random.new(48)) # = [8,10,1] 我写了一个小的单比特测试,看看一个值在洗牌数组中出现的次数
使用Array #shuffle时,Ruby允许使用自定义随机函数,甚至提供Random类来使用它.以下示例使用种子值为48的类.

array = [1,2,3,4,5,6,7,8,9,10]
array.shuffle(random: Random.new(48))  # => [8,10,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,但是shuffling会产生以下分布:

1:  0
2:  5423
3:  5562
4:  5544
5:  5512
6:  5569
7:  5535
8:  5595
9:  5524
10: 5736

如您所见,在数组被洗牌后,数组值1永远不会出现在数组的第一个位置.任何人都知道为什么?

解决方法

有一个 bug in Ruby 2.0.0p0,限制是一个.

这已在Ruby 2.0.0p195中修复,因此您应该升级您的安装.

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读