方案 - 生成随机

tla*_*uer 6 scheme

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

use*_*810 7

标准方案不提供随机数生成器,虽然大多数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))))
Run Code Online (Sandbox Code Playgroud)

调用(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)"))))
Run Code Online (Sandbox Code Playgroud)

诸如此类的随机数对于简单模拟来说足够好,但要注意它们不适用于加密应用程序.如果您有兴趣,我的博客上有几个随机数生成器,包括一些适用于加密应用程序的生成器.


Ósc*_*pez 5

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

(random)
=> 0.9113789707345018
Run Code Online (Sandbox Code Playgroud)

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

(define (random-choice a b)
  (if (zero? (random 2)) a b))
Run Code Online (Sandbox Code Playgroud)

请注意,2传递的参数random强制它随机返回两个可能的值之一:01.所以,如果(random 2)到求值0,然后a返回,否则b返回.

(random-choice 4 2)
=> 4
(random-choice 4 2)
=> 2
Run Code Online (Sandbox Code Playgroud)

  • 不是标准的方案,它不是.大多数实现都有创建随机数的工具,但它们并不都使用相同的名称或相同的签名.例如在Guile中有一个`random`过程,但它至少需要一个参数并且总是返回一个整数.因此,您的代码将导致Guile中的错误(以及许多其他Scheme实现,我想).如果没有标准答案,可以给出特定于实现的答案,但至少应该提到它是特定于实现的,以及它是特定的实现. (3认同)