【问题标题】:How do I write a simulation in r for a "gambling" problem and return probability?如何在 r 中为“赌博”问题和返回概率编写模拟?
【发布时间】:2019-11-10 00:18:23
【问题描述】:

我正在尝试在 R 中运行模拟,但我不确定从哪里开始。问题如下:

“你有 100 美元,并且在一场公平的游戏中下注 10 美元。到你第 100 次下注时,你输掉所有钱的概率是多少?”

到目前为止,我已经编写了一个小函数来从“硬币翻转”中生成随机结果,但这就是我所得到的。

win.lose <- function(x){
  sample(0:1, x, rep=TRUE)
}

我担心的是这个功能不考虑从奖金中赚钱。在这里为上述问题编写更好的函数的一些帮助将不胜感激。谢谢!

【问题讨论】:

    标签: r function simulation


    【解决方案1】:

    使用矢量化效果最好。我们应该一次采样而不是循环:

    sample(c(-1, 1), 100, replace = TRUE)
    

    我们也知道,如果我们净亏损 10 次,我们就会破产。转换为累积总和:

    cumsum(sample(c(-1, 1), 100, replace = TRUE))
    
    any(cumsum(sample(c(-1, 1), 100, replace = TRUE)) == -10)
    

    最后,我们可以使用replicate() 重复这个完全相同的模拟:

    #specify simulation criteria
    n <- 100 
    n_sim <- 10
    
    # betting criteria
    n_broke <- 10 #if we have 10 net losses, we're broke
    bet <- 10 #each bet is $10
    
    # way 1
    set.seed(123)
    replicate(n_sim, cumsum(sample(c(-1, 1), n, replace = TRUE))) 
    
    #or with actual money totals - note, 1st row is the initial money amount
    set.seed(123)
    replicate(n_sim, cumsum(c(n_broke * bet, bet * sample(c(-1, 1), n, replace = TRUE))))
    
    #or a summary of it:
    set.seed(123)
    table(replicate(n_sim, ifelse(any(cumsum(sample(c(-1, 1), n, replace = TRUE)) == -n_broke), 'Out_of_Money', 'Has_Money')))
    
    #faster way to do it:
    set.seed(123)
    table(
      ifelse(
        apply(matrix(sample(c(-1,1), n * n_sim, replace = TRUE), ncol = n_sim),
              2,
              function(x) min(cumsum(x)) <= -n_broke),
        'Out_of_Money', 'Has_Money')
    )
    

    对于 n_sim = 10,000:

       Has_Money Out_of_Money 
            6783         3217 
    

    以及幕后发生的事情:

    set.seed(123)
    replicate(n_sim, cumsum(c(n_broke * bet, bet * sample(c(-1, 1), n, replace = TRUE))))
           [,1] [,2] [,3] [,4] [,5] [,6] [,7] [,8] [,9] [,10]
      [1,]  100  100  100  100  100  100  100  100  100   100
      [2,]   90   90  110  110   90  110  110  110   90   110
      [3,]   80  100  120  120   80  120  120  100   80   120
      [4,]   70  110  130  110   70  130  130   90   90   110
      [5,]   80  100  120  120   60  140  120   80  100   100
      [6,]   70  110  130  110   50  130  110   90   90   110
      [7,]   80  120  140  100   40  120  100   80   80   120
      [8,]   90  110  150  110   50  110   90   70   70   130
      [9,]  100  100  140  100   40  100  100   60   60   120
    

    【讨论】:

    • 这太棒了!非常感谢您的帮助!
    【解决方案2】:

    这是binomial 分布的一个简单问题。

    • 首先:由于我们有兴趣计算“到您第 100 次下注时的概率,我们需要计算在第 100 次之前我们最多可以成功多少次试用以耗尽金钱: 需要求解的方程是:100 + 20*X + (99 - X)*(-10) &lt;= 0,其中X 是在 99 次试验中应该取得的必要成功次数。这只会导致 36 成功。
    • 第二:既然我们已经知道99赌注需要36成功,我们可以使用pbinom函数来计算得到36或更少的概率成功如果我们赌了 99 次:

      pbinom(36,99,0.5)

    导致0.004316793的概率。

    这是一个公平游戏的通用框架,可用于任何数量的初始财富、赌金和终止审判。

    注意:顺便说一下,与任何模拟方法相比,这都会计算出准确的概率!

    【讨论】:

    • 但是模拟更有趣! +1 解释。
    【解决方案3】:

    您可以像这样模拟 100 次投注。

    library(dplyr)
    
    current_balance <- 100
    bet <- 10
    odds <- 0.5
    
    for(i in 1:100) {
    
      current_balance <- current_balance - bet # place bet
    
      outcome <- ifelse(runif(1) > 0.5, 
                        bet * 2, # win: receive twice the bet ($20)
                        0) # lose and the initial $10 is lost
    
      current_balance <- current_balance + outcome
    
      paste("Balance after", i, "bets is:", current_balance) %>% print
    
      if(current_balance <= 0) { stop() }
    }
    
    

    您可以将整个事情包装在另一个循环中以多次运行模拟,并记录结果,就像这样

    ending_balances <- c()
    
    for(s in 1:10) {
    
    current_balance <- 100
    bet <- 10
    odds <- 0.5
    
      for(i in 1:100) {
    
        current_balance <- current_balance - bet # place bet
    
        outcome <- ifelse(runif(1) > 0.5, 
                          bet * 2, # win: receive twice the bet ($20)
                          0) # lose and the initial $10 is lost
    
        current_balance <- current_balance + outcome
    
        # paste("Balance after", i, "bets is:", current_balance) %>% print
    
        if(current_balance <= 0) { 
    
          ending_balances[s] <- current_balance
          break() 
          }
    
        ending_balances[s] <- current_balance
    
      }
    
    }
    
    
    
    > ending_balances
     [1]   0  80 220  60   0 120   0  80   0 200
    

    【讨论】:

      【解决方案4】:

      我们可以将函数写入sample -10(输)和 20(赢)100 次,如果在 100 次投注中的任何时候我们输掉了所有的钱(100 美元),则返回 TRUE

      lost.balance <- function() {
        total <- cumsum(sample(c(-10, 20), 100, replace = TRUE))
        any(total <= -100)
      }
      

      我们可以用replicaten模拟次数,用table计算比例

      n <- 10000
      table(replicate(n, lost.balance()))/n
      
      #   FALSE   TRUE 
      #  0.9902 0.0098 
      

      【讨论】:

        【解决方案5】:

        既然你有 100,你使用 10,那么你只有 90。这里的诀窍是,如果你赢了,你的收益是多少。如果是double,则需要sample(c(-1,2), 100, rep=TRUE)

        win.lose <- function(){
            total <- 90
                for(i in c(1:100)){
                        bet_output <- sample(c(-1,2), 1, rep=TRUE)
                        total <- total + 10 * bet_output
                        if(total<0) return(total)
                }
                return(total)
        }
        
        sim_y <- unlist(lapply(c(1:10000), function(i){win.lose()} ))
        sum(sim_y < 0)/length(sim_y)
        

        【讨论】:

          猜你喜欢
          • 2021-11-18
          • 2017-11-21
          • 2019-07-26
          • 2016-02-29
          • 1970-01-01
          • 1970-01-01
          • 2013-11-10
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多