R 中的强力球:如何 运行 更快?
Powerball in R: how to run faster?
只是为了好玩,我正在 运行ning 随机数生成器来获取强力球号码 + 强力球。下面的代码。它很慢。如果我想 运行 它 1000 次来获取统计信息——这将需要很长时间。
建议如何加快速度?摆脱循环?
注意:两个随机数是必须的,因为强力球本身是一个单独的桶。
这里没什么大不了的。只是找点乐子。 (第 1 次 运行 成功获得 175,226,831)
pwr_win = "4 8 19 27 34 10"
n = 500000000
win = 0
for (i in 1:n) {
if (i %% 100000 == 0) print(i)
tmp = paste(paste(sort(sample(1:69,5)),collapse = " "),sample(1:26,1),collapse = " ")
if (tmp == pwr_win) {
print(paste("win",i))
win = i
}
}
print(win)
编辑:所需的性能是 - 运行 获得中奖试用号码(无限次尝试)的代码,比如 290,000,000。重复多次取平均值证明1/292M可抢性。
我认为使用整数而不是比较字符串会更有效率。下面的函数 pbSim()
将中奖号码作为输入,抽取一次强力球,比较两个强力球,如果它们匹配,则继续抽取剩余号码。否则亏损退出。然后你可以复制那么多次,你可能永远不会赢。
pbSim <- function(numbers) {
if(!is.integer(numbers))
numbers <- as.integer(numbers)
if(identical(sample(21, 1), tail(numbers, 1L))) {
draw <- sample(69, 5)
identical(sort(draw), head(numbers, -1L))
} else FALSE
}
pwr_win <- c(4, 8, 19, 27, 34, 10)
pbSim(pwr_win)
# [1] FALSE
replicate(10, pbSim(pwr_win))
# [1] FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
好的,让游戏规则稍微精简一下。我会更改我的答案,但一般方法是相同的——避免对单张票进行迭代。
估计有
tickets = choose(69, 5) * 26 # 292201338
可能的门票。其中一位获胜
winner = sample(tickets, 1)
你想玩多张门票,购买替换 purchases = sample(tickets, tries, TRUE)
,并重复直到你有一个赢家
set.seed(123)
tries <- 100000000; n <- 0
repeat {
purchases = sample(tickets, tries, TRUE)
idx <- which(purchases == winner)
if (length(idx))
break
n <- n + tries
message(n)
}
当第一个获胜者是
时,循环在第二次迭代(几秒钟)期间退出
> n + idx[1]
[1] 136801728
已购票。
但是,一旦确定了获胜的概率,就很容易产生购买获胜者之前的等待时间。选择获胜者是一个泊松过程,第一次成功之前的等待时间呈几何分布。可以使用 rgeom(1000, 1 / tickets)
快速模拟 1000 次获胜(即 1000 张中奖彩票)的等待时间,但不幸的是,这会导致 R 中的整数溢出,因此我们手动计算这些
wait = log(runif(1000)) / log(1 - 1 / tickets)) + 1
只是为了好玩,我正在 运行ning 随机数生成器来获取强力球号码 + 强力球。下面的代码。它很慢。如果我想 运行 它 1000 次来获取统计信息——这将需要很长时间。
建议如何加快速度?摆脱循环? 注意:两个随机数是必须的,因为强力球本身是一个单独的桶。
这里没什么大不了的。只是找点乐子。 (第 1 次 运行 成功获得 175,226,831)
pwr_win = "4 8 19 27 34 10"
n = 500000000
win = 0
for (i in 1:n) {
if (i %% 100000 == 0) print(i)
tmp = paste(paste(sort(sample(1:69,5)),collapse = " "),sample(1:26,1),collapse = " ")
if (tmp == pwr_win) {
print(paste("win",i))
win = i
}
}
print(win)
编辑:所需的性能是 - 运行 获得中奖试用号码(无限次尝试)的代码,比如 290,000,000。重复多次取平均值证明1/292M可抢性。
我认为使用整数而不是比较字符串会更有效率。下面的函数 pbSim()
将中奖号码作为输入,抽取一次强力球,比较两个强力球,如果它们匹配,则继续抽取剩余号码。否则亏损退出。然后你可以复制那么多次,你可能永远不会赢。
pbSim <- function(numbers) {
if(!is.integer(numbers))
numbers <- as.integer(numbers)
if(identical(sample(21, 1), tail(numbers, 1L))) {
draw <- sample(69, 5)
identical(sort(draw), head(numbers, -1L))
} else FALSE
}
pwr_win <- c(4, 8, 19, 27, 34, 10)
pbSim(pwr_win)
# [1] FALSE
replicate(10, pbSim(pwr_win))
# [1] FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
好的,让游戏规则稍微精简一下。我会更改我的答案,但一般方法是相同的——避免对单张票进行迭代。
估计有
tickets = choose(69, 5) * 26 # 292201338
可能的门票。其中一位获胜
winner = sample(tickets, 1)
你想玩多张门票,购买替换 purchases = sample(tickets, tries, TRUE)
,并重复直到你有一个赢家
set.seed(123)
tries <- 100000000; n <- 0
repeat {
purchases = sample(tickets, tries, TRUE)
idx <- which(purchases == winner)
if (length(idx))
break
n <- n + tries
message(n)
}
当第一个获胜者是
时,循环在第二次迭代(几秒钟)期间退出> n + idx[1]
[1] 136801728
已购票。
但是,一旦确定了获胜的概率,就很容易产生购买获胜者之前的等待时间。选择获胜者是一个泊松过程,第一次成功之前的等待时间呈几何分布。可以使用 rgeom(1000, 1 / tickets)
快速模拟 1000 次获胜(即 1000 张中奖彩票)的等待时间,但不幸的是,这会导致 R 中的整数溢出,因此我们手动计算这些
wait = log(runif(1000)) / log(1 - 1 / tickets)) + 1