【问题标题】:Random number generator in haskell using recursion使用递归的haskell中的随机数生成器
【发布时间】:2020-09-28 11:26:39
【问题描述】:

我有以下练习:

在许多计算机程序中,我们需要一个随机数生成器。这些生成器产生的数字 并不是真正随机的,但它们似乎是随机的。这就解释了为什么这些生成器有时 称为伪随机发生器。这种类型的最简单的生成器之一是所谓的线性 同余 发生器 .这些生成器使用递归生成一系列数字 X_i X_i+1 = (a · X_i + c) mod m。 必须明智地选择参数 a、c 和 m 的值。如果您对如何选择这些值感兴趣,那么您可能需要阅读https://en.wikipedia.org/wiki/Linear_congruential_generator

在本练习中,我们选择 X_0 = 2773639、a = 25214903917、c = 11 和 m = 2^45。 给出一个无限列表 random :: [Integer] 的 Haskell 实现,它返回的无限列表 这组参数生成的随机数。随机取 n 的时间复杂度应为 在 n 中是线性的。表达式 take 6 random 应导致: [2773639,25693544934790,35087648281,25863180521136,928172761339,19643099434218]

我是 Haskell 的新手,我不知道如何生成一个无限列表,甚至这个函数的参数应该是什么。此外,递归性使其变得更加困难,因为我不确定如何编写基本案例。到目前为止,我已经尝试过:

random :: Int -> [a]

random 0 = 2773639
random x = [x | x <- (25214903917 * random (x-1) + 11 ) `mod` (2^45)]

这显然是有缺陷的,但我无法提出其他建议,因为我没有足够的 Haskell 经验,甚至无法考虑其他可能性。感谢您的宝贵时间!

【问题讨论】:

  • 对于无限列表,没有基本情况。由于 Haskell 的惰性,它不会评估下一个项目,如果它不需要另一个项目。
  • 提示:您想编写一个函数,返回所有随机数,其中参数是列表中的第一个随机数。提示2:这意味着它返回第一个随机数(参数),然后是从第二个开始的所有随机数(根据第一个计算)。
  • 提示:要生成一个无限列表,您可以简单地在尾部递归。例如。 f n = n : f (n+1) 将从n 开始生成无限的数字列表。您可以尝试调整这条线路以满足您的需求。
  • 提示:random (x -1)X_{i-1} 不同。您需要访问先前的值,例如使用显式递归函数或 zip。
  • 谢谢你,我终于可以做到了!

标签: haskell functional-programming


【解决方案1】:

我能够用该代码解决它:

random :: [Integer] 

random = f 2773639 
       where f x = x : f((25214903917 * x + 11) `mod` (2^45)) 

【讨论】:

    【解决方案2】:

    您的方法是一种选择;一种更清洁的方法是

    random :: [Integer] 
    random = iterate (\x -> (25214903917 * x + 11) `mod` 2^45) 2773639
    

    或者,使用无点样式,

    random = iterate ((`mod` 2^45) . (+11) . (25214903917*)) 2773639
    

    我会说,由于你的同余只有 45 位,你不需要在这里使用 IntegerInt(或者,为了平台安全,Data.Int.Int64)就足够了,而且更好,因为它是速度更快,并暗示实际输出的数字有多大。

    【讨论】:

      猜你喜欢
      • 2019-08-03
      • 1970-01-01
      • 1970-01-01
      • 2015-01-15
      • 1970-01-01
      • 2015-12-30
      • 1970-01-01
      • 1970-01-01
      • 2015-01-26
      相关资源
      最近更新 更多