方案 - 生成随机

时间:2013-02-03 15:40:22

标签: scheme

如何在Scheme中生成随机数?有特殊形式还是我必须创建一个程序?如果是这样,我该怎么做? (我正在尝试创建一个名为random-choice的过程,它输入两个策略并随机返回一个。)

3 个答案:

答案 0 :(得分:6)

标准方案不提供随机数生成器,虽然大多数Scheme实现提供了一个,但它们的细节往往不同。如果你想编写一个便携式的Scheme程序,很容易建立你自己的随机数生成器;这是Knuth的方法:

(define random
  (let ((a 69069) (c 1) (m (expt 2 32)) (seed 19380110))
    (lambda new-seed
      (if (pair? new-seed)
          (set! seed (car new-seed))
          (set! seed (modulo (+ (* seed a) c) m)))
      (/ seed m))))

调用(random)会返回0(含)和1(不包含)之间的随机分数。随机分数循环,周期 m 。调用(random seed)重置随机数生成器的种子,以便从同一种子开始的两个随机序列将是相同的; YYYYMMDD形式的日期是好种子(那是Knuth的生日)。如果您想翻转硬币,请说:(if (< (random) 1/2) 'heads 'tails)

有时你想要一个范围内的随机整数。下面显示的randint函数会将 lo (包括)范围内的随机整数返回到 hi (不包括); lo 默认为0:

(define (randint . args)
  (cond ((= (length args) 1)
          (floor (* (random) (car args))))
        ((= (length args) 2)
          (+ (car args) (floor (* (random) (- (cadr args) (car args))))))
        (else (error 'randint "usage: (randint [lo] hi)"))))

这些随机数对于简单模拟来说已经足够了,但要注意它们不适合加密应用程序。如果您有兴趣,我会在my blog有几个随机数生成器,包括一些适用于加密应用程序的生成器。

答案 1 :(得分:5)

令人惊讶的是,random调用了该过程 - 尽管确切的语法可能会有所不同,具体取决于使用的Scheme解释器(请阅读文档!),但总体思路如下:

(random)
=> 0.9113789707345018

如果要返回两个可能值中的一个,这将在Racket中完成:

(define (random-choice a b)
  (if (zero? (random 2)) a b))

请注意,传递给2的{​​{1}}参数会强制它随机返回两个可能值中的一个:random0。因此,如果1评估为(random 2),则会返回0,否则会返回a

b

答案 2 :(得分:1)

由于您的另一个问题是关于在DrRacket中实施太空飞船游戏,我将假设,您通过Scheme表示DrRacket中的一种教学语言。

在DrRacket中查找有关可用功能的信息的方法很简单。比如说,在交互窗口中写random。将光标置于顶部,然后按F1。

htdp-languages中random的文档在这里:

http://docs.racket-lang.org/htdp-langs/beginner.html?q=random#(def.htdp-beginner.((lib._lang/htdp-beginner..rkt)._random))

返回随机值的一种方法:

(list-ref (list "one" "two") (random 2))

这里(随机2)将返回0或1。 因此list-ref将返回条目 使用列表的索引0或索引1。

使用上述方法的优点 是很容易扩展到更多的价值观 不止两个。