如何在 Common Lisp 中生成 [0 ... 1.0] 中的随机数

Dr *_*nan 2 lisp random probability

我对 Common Lisp 伪随机数生成的理解是,它将(random 1.0)生成一个严格小于 1 的分数。我希望得到 1.0 以内的数字。这可能吗?我想我可以决定精度并生成整数并除以范围,但我想知道是否有更广泛接受的方法来做到这一点。谢谢。

ign*_*ens 7

正如你所说,random默认会生成 [0,1) 中的数字,并且一般(random x)会生成 [0,x) 中的随机数。如果这些是实数并且分布确实是随机的,那么获得任何数字的概率为零,因此这实际上与 [0,1] 没有什么不同。但它们不是实数:它们是浮点数,因此获得任何特定值的概率较高,因为 [0,1] 中只有有限数量的浮点数。

幸运的是,您可以准确地表达您想要的内容:CL 有一堆名称如 * 的常量,-epsilon它们的定义是这样的,例如

(/= (+ 1.0f0 single-float-epsilon) 1.0f0)
Run Code Online (Sandbox Code Playgroud)

并且是满足此条件的single-float-epsilon最小的。single-float

因此(random (+ 1.0f0 single-float-epsilon))将产生 [0,1] 范围内的随机单浮点,并且最终可能会结果为1.0f0。你可以测试一下:

(defun tsit ()
  (let ((f (+ 1.0f0 single-float-epsilon)))
    (assert (/= f 1.0f0) (f) "oops")
    (loop for i upfrom 1
          for v = (random f)
          when (= v 1.0f0)
          return (values i v))))
Run Code Online (Sandbox Code Playgroud)

而对于我来说

> (tsit)
12839205
1.0
Run Code Online (Sandbox Code Playgroud)

如果您使用双浮点数,则需要......相当长的时间......才能获得1.0d0(并记住使用double-float-epsilon)。