Lisp偏差数字生成器

时间:2015-03-31 03:05:56

标签: random lisp common-lisp sbcl

有没有办法在lisp中的随机生成器中指定偏差?

例如,如果我有一系列数字。如何指定范围前半部分的数字比后半部分的数字高出3倍?

2 个答案:

答案 0 :(得分:2)

分两步完成:

首先,在某个任意范围内选择一个随机数,并确定它是否在该范围的前3/4。如果是,则在给定范围的前半部分选择一个随机数,否则在下半部分选择一个随机数:

(defun biased_random(low high) {
    (let ((temp (random 1.0))
          (middle (floor (+ high low) 2)))
      (if (< temp 0.75)
          (+ low (random (- middle low)))
          (+ middle (random (- high middle)))))

答案 1 :(得分:2)

我喜欢Barmar's answer,它可以很好地处理任意权重。但是,它需要两次调用随机,这可能是不受欢迎的。另一种方法是创建具有根据其预期频率出现的元素的向量。例如,如果您的元素a和b应该以1/3和2/3的概率选择,那么您可以创建一个数组(a b b)并从中随机选择。

(defun biased-generator (values weights)
  (multiple-value-bind (total values)
      (loop for v in values
         for w in weights
         nconc (make-list w :initial-element v) into vs
         sum w into total
         finally (return (values total (coerce vs 'vector))))
    (lambda ()
      (aref values (random total)))))

CL-USER> (defparameter *gen* (biased-generator '(a b) '(1 2)))
*GEN*
CL-USER> (loop for i from 1 to 100 collect (funcall *gen*))
(A A B A B A A B B A B B A A A B A A B A A A B A A A B B B B B A B B B B A A B
 A B B A A A A B B B A A A A B A A B B B A A B B B A B B B B B B B B B B A B A
 A A A B B B B A B A A B B A B A A B B B B B)
CL-USER> (let ((abs (loop for i from 1 to 10000 collect (funcall *gen*))))
           (list (count 'a abs)
                 (count 'b abs)))
(3293 6707)