SIMPLE随机数生成

时间:2012-03-16 20:21:03

标签: haskell random quickcheck

经过一段令人沮丧的研究之后,我正在写这篇文章,我希望这里有人能够启发我这个主题。

我想在haskell函数中生成一个简单的随机数,但是,如果没有各种非平凡的元素,例如Monads,“do”中的asignation,创建生成器等,这似乎是不可能的。

理想情况下,我正在寻找相当于C的“rand()”。但经过多次搜索,我很确信没有这样的东西,因为语言是如何设计的。 (如果有,请有人赐教)。由于这似乎不可行,我想找到一种方法来获取我的特定问题的随机数,以及关于如何获得随机数的一般解释。

prefixGenerator :: (Ord a, Arbitrary a) => Gen ([a],[a])
prefixGenerator = frequency [ 
    (1, return ([],[])),
    (2, do {
            xs1 <- orderedListEj13 ;
            xs2 <- orderedListEj13 ;
            return (xs1,xs2)
       }),
    (2, do {                
            xs2 <- orderedListEj13 ;
            return ((take RANDOMNUMBERHERE xs2),xs2)
       })
    ]

我正在尝试使用QuickCheck,但我无法使用随机数字使其变得困难。我尝试过类似this的东西(通过放置一个drawInt 0(长度为xs2)而不是RANDOMNUMBERHERE)但是我不知道take需要一个Int而且该方法给我留下了IO Int,这似乎是不可能的根据{{​​3}}转换为Int。

3 个答案:

答案 0 :(得分:6)

由于haskell是一种函数式编程语言,函数是引用透明,这意味着只有函数的参数才能确定其结果。如果你能够从空中拉出一个随机数,你可以想象这会如何导致问题。

我想你需要这样的东西:

prefixGenerator :: (Ord a, Arbitrary a) => Gen ([a],[a])
prefixGenerator = do
  randn <- choose (1,999) -- number in range 1-999
  frequency [ 
    (1, return ([],[])),
    (2, do {
            xs1 <- orderedListEj13 ;
            xs2 <- orderedListEj13 ;
            return (xs1,xs2)
       }),
    (2, do {                
            xs2 <- orderedListEj13 ;
            return ((take randn xs2),xs2)
       })
    ]

通常在haskell中,您可以通过从IO monad中提取一些随机数,或者通过维护一个使用硬编码的整数种子进行初始化的PRNG,或者从IO中提取(gspr的评论非常好)来实现随机数生成。 / p>

阅读伪随机数生成器的工作原理可能有助于您理解System.Random,而this也可能有所帮助(向下滚动到随机性部分)。

答案 1 :(得分:4)

你是正确的 nondeterministic 随机(我的意思是“伪随机”)数字生成是不可能没有欺骗。 Haskell中的函数是 pure ,这意味着相同的输入将始终产生相同的输出。

好消息是你似乎不需要一个不确定的PRNG。事实上,如果你的QuickCheck测试每次使用相同的序列的“随机”数字会更好,以使你的测试完全可重复。

您可以使用System.Random中的mkStdGen功能执行此操作。改编自Haskell wiki

import System.Random
import Data.List

randomInts :: Int -> [Int]
randomInts n = take n $ unfoldr (Just . random) (mkStdGen 4)

此处,4是您可能希望通过fair dice roll选择的种子。

答案 2 :(得分:3)

标准库提供了一个用于随机数生成的monad。 monadic的东西并不难学,但如果你想避免它,找一个伪随机函数next,以伪随机的方式将Int带到Int,并且然后只需创建并传递无限的随机数列表:

next :: Int -> Int
randoms :: [Int]
randoms = iterate next 73

然后,您可以在任何需要的地方传递此随机数列表。

这是来自维基百科的线性同余next

next n = (1103515245 * n + 12345) `mod` 1073741824

以下是73之后的前20个伪随机数:

Prelude> take 20 $ iterate next 73
[73,25988430,339353199,182384508,910120965,1051209818,737424011,14815080,325218177,1034483750,267480167,394050068,4555453,647786674,916350979,980771712,491556281,584902142,110461279,160249772]
相关问题