我认为我在这里做错了什么:
ghci> take 10 $ randomRs (1,6) (mkStdGen 2)
[6,4,1,5,4,2,2,2,2,3]
ghci> take 10 $ randomRs (1,6) (mkStdGen 3)
[6,4,5,4,4,2,1,1,5,1]
ghci> take 10 $ randomRs (1,6) (mkStdGen 5)
[6,2,2,1,3,2,5,1,5,4]
ghci> take 10 $ randomRs (1,6) (mkStdGen 7)
[6,1,4,5,3,2,3,6,6,6]
ghci> take 10 $ randomRs (1,6) (mkStdGen 11)
[6,4,4,6,1,2,6,5,6,5]
为什么第一个随机数总是“随机”6 ......?
对于从a到z的字母,“n”的相同模式:
ghci> take 10 $ randomRs ('a','z') (mkStdGen 13)
"nnofwbxbtw"
ghci> take 10 $ randomRs ('a','z') (mkStdGen 17)
"novkmtfugl"
ghci> take 10 $ randomRs ('a','z') (mkStdGen 19)
"nhurafjvey"
我通过LYAHFGG(第9章关于随机性)偶然发现了这一点并且真的没有理解它。我希望种子没有模式。
答案 0 :(得分:6)
System.Random.StdGen
是一个可怕的发电机,很久以前就应该更换了。甚至还有快速检查属性显然是错误的,由于StdGen
的质量差导致数千次检查后仍然通过,并且这是通过良好的播种来完成的。
有许多强大的生成器,包括加密种类和统计数据。对于加密随机生成器,请考虑使用tf-random
包替换为StdGen
,DRBG
,或者为快速且统计上良好的生成器使用mersenne-random-pure64
。
答案 1 :(得分:3)
这些种子都是非常小的数字,比如maxBound :: Int
小得多。因此,它们不是随机发生器的现实世界内部状态的代表性样本。基本上,randomR
的第一个结果只是"随机种子"随机,WRT各自的范围。
如果你想要第一个结果的变化,你需要正确地散列种子,所以这些值在允许的整数范围内分散。最简单的方法是丢弃第一个结果。