首页 文章

SIMPLE随机数生成

提问于
浏览
5

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

我想在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)
       })
    ]

我'm trying to get to grips with QuickCheck but my inability to use random numbers is making it hard. I'尝试了类似this的东西(通过放置一个drawInt 0(长度为xs2)而不是RANDOMNUMBERHERE)但是我坚持认为take需要一个Int并且该方法留给我一个IO Int,这似乎无法转换为一个Int根据this .

3 回答

  • 4

    标准库提供了用于随机数生成的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]
    
  • 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的评论非常好)来实现随机数生成 .

    阅读伪随机数生成器如何工作可能有助于您理解 System.Randomthis也可能有所帮助(向下滚动到随机性部分) .

  • 3

    如果没有诡计,你的数字生成是不可能的,那就是非确定性随机(我的意思是"pseudo-random") . Haskell中的函数是纯函数,这意味着相同的输入将始终产生相同的输出 .

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

    您可以使用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选择的种子 .

相关问题