编写R函数模拟硬币翻转游戏,计算10万次模拟的期望收益
问题描述
游戏规则为:反复抛掷公平硬币,直到正面(heads)与反面(tails)的数量差达到3时停止;最终可获得8美元,但每次抛掷需支付1美元。需要通过100000次模拟计算期望收益。现有单局游戏的R代码,但运行10万次时效率极低,需改写为高效计算10万次游戏期望收益的函数。
原单局代码:
# 单局游戏示例 # 游戏次数 n_games <- 1 bias <- 0.5 game_payoff <- c() for (i in seq_len(n_games)) { cost <- 0 flip_record <- c() payoff <- c() repeat{ cost <- cost + 1 flip <- rbinom(1, 1, prob = bias) flip_record <- c(flip_record, flip) # 反面(0)的数量 n_tails <- length(flip_record) - sum(flip_record) # 正面(1)的数量 n_heads <- sum(flip_record) if (abs(n_tails - n_heads) == 3) { # 记录本局收益 game_payoff <- c(game_payoff, 8 - cost) # 打印本局收益 print(paste0("单局收益: ", 8 - cost)) break } } }
优化后的高效模拟函数
simulate_game <- function(n_games, bias = 0.5) { # 预分配收益结果向量,避免动态扩容的性能损耗 payoffs <- numeric(n_games) for (i in seq_len(n_games)) { # 跟踪正反面数量差:正面+1,反面-1 diff <- 0 cost <- 0 repeat { cost <- cost + 1 # 单次抛掷,直接更新差值 diff <- diff + sample(c(1, -1), 1, prob = c(bias, 1 - bias)) # 差值达到±3时停止本局 if (abs(diff) == 3) { payoffs[i] <- 8 - cost break } } } # 返回所有游戏的期望收益 mean(payoffs) } # 执行10万次模拟 expected_payoff <- simulate_game(100000) cat("模拟得到的期望收益为:", expected_payoff, "美元\n")
核心优化说明
- 预分配内存:原代码中
game_payoff <- c(game_payoff, ...)每次都会重新分配并复制向量,10万次操作会产生巨大的性能开销。优化后直接创建固定长度的numeric(n_games),内存使用更高效。 - 简化状态跟踪:原代码保存所有抛掷记录并反复计算正反面数量,完全没必要。直接跟踪正反面的数量差
diff,每次抛掷后更新差值,大幅减少计算量。 - 简化抛掷逻辑:用
sample(c(1,-1))直接表示正面(+1)和反面(-1),一步到位更新差值,比rbinom生成0/1后再计算差值的流程更简洁高效。 - 移除冗余操作:原代码的打印操作在10万次模拟中会严重拖慢速度,优化后仅在最后输出最终的期望收益结果。
内容的提问来源于stack exchange,提问作者user14428298
相关产品推荐
相关产品推荐

