生成随机数,不包括单个数字

Car*_*ate 6 random clojure

我正在写一个Monty Hall模拟器,发现需要在一个范围内生成一个数字,不包括一个数字.

这似乎很容易,所以我天真地写道:

(这些g/...功能是我个人图书馆的一部分.它们的使用应该相当清楚):

(defn random-int-excluding
  "Generates a random number between min-n and max-n; excluding excluding-n.
  min-n is inclusive, while max-n is exclusive."
  [min-n max-n excluding-n rand-gen]
  (let [rand-n (g/random-int min-n max-n rand-gen)
        rand-n' (if (= rand-n excluding-n) (inc rand-n) rand-n)]
    (g/wrap rand-n' min-n (inc max-n))))
Run Code Online (Sandbox Code Playgroud)

这会在范围内生成一个随机数,如果它等于排除的数字,则加一; 必要时包装.当然,最终在被排除的数字之后给出数字两倍的被挑选机会,因为如果选择它或被排除的数字,它将被挑选.样本输出频率范围为0到10(最大不包括),不包括2:

([0 0.099882]
 [1 0.100355]
 [3 0.200025]
 [4 0.099912]
 [5 0.099672]
 [6 0.099976]
 [7 0.099539]
 [8 0.100222]
 [9 0.100417])
Run Code Online (Sandbox Code Playgroud)

然后我读了这个看起来更简单的答案,并在此基础上写道:

(defn random-int-excluding
  "Generates a random number between min-n and max-n; excluding excluding-n.
  min-n is inclusive, while max-n is exclusive."
  [min-n max-n excluding-n rand-gen]
  (let [r1 (g/random-int min-n excluding-n rand-gen)
        r2 (g/random-int (inc excluding-n) max-n rand-gen)]
    (if (g/random-boolean rand-gen) r1 r2)))
Run Code Online (Sandbox Code Playgroud)

基本上,它将范围拆分为2个较小的范围:从最小值到排除数字,从排除数字+ 1到最大值.它从这些范围生成随机数,然后随机选择其中一个.不幸的是,正如我在答案中指出的那样,除非两个分区的大小相等,否则会产生偏差.样本输出频率; 与上述条件相同:

([0 0.2499497]
 [1 0.2500795]
 [3 0.0715849]
 [4 0.071297]
 [5 0.0714366]
 [6 0.0714362]
 [7 0.0712715]
 [8 0.0715285]
 [9 0.0714161])
Run Code Online (Sandbox Code Playgroud)

请注意,排除数字之前较小范围的数字部分更有可能.为了解决这个问题,我不得不倾向于更频繁地从更大的范围中选择数字,而且实际上,我并不精通数学,因此理解如何做到这一点.

我查看了链接问题中接受的答案,但对我来说,这似乎是我第一次尝试接受超过1个数字排除的版本.我希望,与回答者所声称的一样,排除范围结束时的数字会受到青睐,因为如果选择的数字在排除范围内,它只会使数字超出范围.

由于这将是模拟中最被称为函数之一,我真的想避免使用"强力"循环方法,同时排除生成的数字,因为范围只有3个数字,所以有一个每次尝试都需要再次尝试1/3的几率.

有没有人知道从连续范围中选择随机数的简单算法,但排除一个数字?

ama*_*loy 6

要生成[a, b]排除范围内的数字c,只需生成范围内的数字,然后输出[a, b-1]结果.cb


Clo*_*tly 2

只需生成一个惰性序列并过滤掉您不需要的项目:

(let [ignore #{4 2}]
  (frequencies
    (take 2000
          (remove ignore (repeatedly #(rand-int 5))))))
Run Code Online (Sandbox Code Playgroud)

映射到不同新值的其他方法的优点:该函数还适用于不同的离散随机数分布