#失礼します。randomの挙動について質問があります。
#例えば(0.25 0.25 0.25 0.25)のような、全体で1となる確率分布のリストを引数にとって、その確率分布に従う乱数を発生させる関数を書きたいのですが、
#(defun sampler (prob-list)
(position-if (lambda (x)
(< (random 1.0) x)) (cumulo-prob-list prob-list)))
#cumulo-prob-list prob-listは(0.25 0.25 0.25 0.25)を(0.25 0.5 0.75 1)のように要素の値を累積させていく関数です。
#(sampler '(0.1 0.1 0.1 0.1 0.1 0.1 0.1 0.1 0.1 0.1))を1万回実行して結果のヒストグラムをつくってみたのですが、 http://twitpic.com/71egvt のように一様分布になりません。 #私もそのようなコードを最初に思いついてACLで今実行してみたら、確かに一様にならないですね。あれー何か見落としてるかなあ。
#randomの問題かと思ってメルセンヌツイスタ(mt19937)でもやってみたのですが、結果は同じでした。
#あーわかった。position-ifで条件判断をする度にrandomを発生させてるからだ。
#(defun sampler (prob-list)
(let ((r (random 1.0)))
(position-if (lambda (x) (< r x)) (cumulo-prob-list prob-list))))
#でどうですか。
#検査の度にrandomしちゃうと、例えば一回目のrandomが0.9で二回めが0.0だった時、それは最初の区分ではなく次の区分にカウントされちゃいます。
#あーなるほど。これでうまくいきました。ありがとうございます!