Random 有偏数发生器

Random 有偏数发生器,random,lisp,common-lisp,sbcl,Random,Lisp,Common Lisp,Sbcl,有没有办法在lisp中指定随机生成器中的偏差 例如,如果我有一系列的数字。如何指定前半个范围内的数字比后半个范围内的数字高3倍?分两步执行: 首先,在任意范围内选择一个随机数,并确定它是否在该范围的前3/4。如果是,则在给定范围的前半部分选择一个随机数,否则在后半部分选择一个随机数: (defun biased_random(low high) { (let ((temp (random 1.0)) (middle (floor (+ high low) 2)))

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

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

分两步执行:

首先,在任意范围内选择一个随机数,并确定它是否在该范围的前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)))))
我喜欢,而且它能很好地处理任意的重量。然而,它确实需要两个随机调用,这可能是不可取的。另一种方法是创建一个向量,其中包含根据预期频率出现的元素。例如,如果元素a和b的概率应为1/3和2/3,则可以创建一个数组a 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)))))

通过RLE将阵列压缩为重量,可以节省空间。值对。然后选择循环该列表,从随机选择的数字中减去权重,直到它是@SamuelEdwinWard,对于大型数据集,这肯定是一个选项,尽管当然有一个折衷,那就是你在做一系列算术,而不是单一的恒定时间访问。对于一些分析来说,这是一个有趣的案例。@SamuelEdwinWard,即使你对累积权重进行了一个assoc,那么主体的结果将类似于cdr assoc random total assoc:test'@Sylvester,这是一个好主意,使用累积权重,你也可以将它们存储在一个数组中并进行二进制搜索。即使我们假设内存不足不是问题,查看一个巨大的数组也会对缓存造成不利影响。我不确定在什么情况下策略是一致的。
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)