Lisp 偏向数生成器
Lisp Biased Number Generator
有没有办法在 lisp 的随机生成器中指定偏差?
例如,如果我有一个数字范围。如何指定范围前半部分数字的可能性是后半部分数字的 3 倍?
分两步完成:
首先,select一个任意范围内的随机数,并判断它是否在该范围的前 3/4 内。如果是,select给定范围前半部分的随机数,否则select后半部分的随机数:
(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)))))
我喜欢 ,它可以很好地处理任意权重。但是,它确实需要两次调用 random,这可能是不受欢迎的。另一种方法是创建一个向量,其中包含根据预期频率出现的元素。例如,如果你有元素 a 和 b 应该以 1/3 和 2/3 的概率选择,那么你可以创建一个数组 (ab b) 和 select 随机从那。
(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)
有没有办法在 lisp 的随机生成器中指定偏差?
例如,如果我有一个数字范围。如何指定范围前半部分数字的可能性是后半部分数字的 3 倍?
分两步完成:
首先,select一个任意范围内的随机数,并判断它是否在该范围的前 3/4 内。如果是,select给定范围前半部分的随机数,否则select后半部分的随机数:
(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)))))
我喜欢
(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)