从硬币翻转算法生成随机均匀随机数往往会生成比预期更多的 0
Generating random uniform random numbers from coin flip algorithm tends to generate more 0s than expected
我正在尝试使用函数 rcoin
生成 0 到 99 范围内的随机数,该函数 returns 0 或 1 的概率相等。我编写了以下代码,将连续调用 rcoin
函数生成的二进制数转换为 returns ,条件是该数字小于 100。这是 R 代码。
rcoin <- function() {
rbinom(n = 1, size = 1, prob = 0.5)
}
r100 <- function(n=100) {
v = n + 1
while(v > n) {
v = sum(sapply(0:6, function(i) rcoin() * 2 ^ i))
}
v
}
val_plot <- function() {
N = 10000
rand_sample <- rep(0, N)
for (i in 1:N){
rand_sample[i] = r100()
}
hist(rand_sample, breaks = 100)
}
val_plot()
它应该产生从 0 到 99 的均匀随机数,因为截断均匀分布也是均匀的。但是当我绘制 10000 个生成值的直方图时,我看到值 0 生成的次数异常多,但所有其他值都遵循均匀分布。为什么?我猜这是因为二进制数“1111111”被拒绝,而“0000000”不是。但是我该如何解决这个问题呢?有什么办法可以改善吗?
这归结为 hist
的使用问题,而不是函数本身。
解决:
1) 将 while(v > n) {
替换为 while(v >= n) {
,因此我们生成小于 100 的数字并拒绝大于或等于 100 的数字。否则 r100
的输出范围为 0 到 100,而不是 0 到 99。
2) 将 hist(rand_sample, breaks = 100)
替换为 hist(rand_sample, breaks = 0:100, right = F)
。否则,默认 hist
设置会将 0 和 1 装箱并使第一个箱看起来太大。
我们也可以从一个简单的内置均匀分布中看到这种行为。
hist(floor(runif(1E6, min = 0, max = 100)), breaks = 100)
hist(floor(runif(1E6, min = 0, max = 100)), breaks = 0:100, right = F)
我正在尝试使用函数 rcoin
生成 0 到 99 范围内的随机数,该函数 returns 0 或 1 的概率相等。我编写了以下代码,将连续调用 rcoin
函数生成的二进制数转换为 returns ,条件是该数字小于 100。这是 R 代码。
rcoin <- function() {
rbinom(n = 1, size = 1, prob = 0.5)
}
r100 <- function(n=100) {
v = n + 1
while(v > n) {
v = sum(sapply(0:6, function(i) rcoin() * 2 ^ i))
}
v
}
val_plot <- function() {
N = 10000
rand_sample <- rep(0, N)
for (i in 1:N){
rand_sample[i] = r100()
}
hist(rand_sample, breaks = 100)
}
val_plot()
它应该产生从 0 到 99 的均匀随机数,因为截断均匀分布也是均匀的。但是当我绘制 10000 个生成值的直方图时,我看到值 0 生成的次数异常多,但所有其他值都遵循均匀分布。为什么?我猜这是因为二进制数“1111111”被拒绝,而“0000000”不是。但是我该如何解决这个问题呢?有什么办法可以改善吗?
这归结为 hist
的使用问题,而不是函数本身。
解决:
1) 将 while(v > n) {
替换为 while(v >= n) {
,因此我们生成小于 100 的数字并拒绝大于或等于 100 的数字。否则 r100
的输出范围为 0 到 100,而不是 0 到 99。
2) 将 hist(rand_sample, breaks = 100)
替换为 hist(rand_sample, breaks = 0:100, right = F)
。否则,默认 hist
设置会将 0 和 1 装箱并使第一个箱看起来太大。
我们也可以从一个简单的内置均匀分布中看到这种行为。
hist(floor(runif(1E6, min = 0, max = 100)), breaks = 100)
hist(floor(runif(1E6, min = 0, max = 100)), breaks = 0:100, right = F)