伪随机的种子问题
最近前端的工作不是很多,所以就帮忙写写后端的 ruby on rails。在写测试用例的时候,虽然单元测试的数据每次都是随机生成的,但是我们需要根据单元测试来生成 API 文档。如果测试文档每次都是随机的数据会很难检查每次 API 更新了什么,所以我们需要在生产测试文档的时候,保证随机数据的稳定性。
# Random seed
seed 的意义就在于,初始化了随机数生成器。保证了每次随机的结果都一样。例如代码:
@rand = Random.new(1234)
puts @rand.rand
puts @rand.rand(0..1050)
puts @rand.rand(0..1050)
puts @rand.rand
1
2
3
4
5
6
7
8
9
2
3
4
5
6
7
8
9
这段代码每次执行都会输出:
0.1915194503788923
674
699
0.2725926052826416
1
2
3
4
2
3
4
# rand range
但是当我们把中间的 rand 的范围稍微修改:
@rand = Random.new(1234)
puts @rand.rand
puts @rand.rand(10..150)
puts @rand.rand(10..150)
puts @rand.rand
1
2
3
4
5
6
7
8
9
2
3
4
5
6
7
8
9
会发现输出发生了变化:
0.1915194503788923
48
63
0.4377277390071145
1
2
3
4
2
3
4
第一次的输出还是不变,当然 2,3 两次肯定是变化的,重点是最后一次。我们发现最后一次的随机数也发生了变化。
# 总结
通过调查 ruby 源码发现,对于有范围的 rand。ruby 会不断生成随机数,判断是否落在区间范围内,如果是在范围内就返回,否则继续尝试。默认在 0 到 1 之间是百分百命中,所以是随机一次。如果是其他范围,命中次数不一样会导致生成随机数的次数发生变化。所以影响到之后的随机数生成。
参考: