【问题标题】:For loop including "if" and "while" running for hoursFor 循环,包括“if”和“while”,运行数小时
【发布时间】:2019-10-03 17:38:44
【问题描述】:

我有一个 for 循环,包括为问题编写的“if”和“while”子句。它旨在在某些条件下进行 1000 次模拟。我认为这不是一个非常复杂的循环,但它已经运行了将近 16 个小时,没有显示结果或提示错误/警告(并且一直显示红色的小停止标志),我可以感觉到我的自从我开始运行循环以来,笔记本电脑的速度变慢了。

所以我想知道这是否真的会发生,或者我的代码或笔记本电脑是否有任何问题。任何帮助是极大的赞赏!!

代码如下:

result.Vec <- NULL
for (trials in 1:1000) {
  sum <- 0
  sum2 <- 0
  n <- 0
  tmp1 <- sample(x=c(1, 2, 3, 4, 5, 6), size=1, replace=T, prob=c(1/6, 1/6, 1/6, 1/6, 1/6, 1/6)) 
  tmp2 <- sample(x=c(1, 2, 3, 4, 5, 6), size=1, replace=T, prob=c(1/6, 1/6, 1/6, 1/6, 1/6, 1/6)) 
  sum <- tmp1 + tmp2
  if (sum == 7 || sum == 11) {
    n <- 1
   } else if (sum == 2 || sum == 3 || sum == 12) {
    n <- 0
   } else {
     while (sum2 != sum || sum2 != 7) {
       tmp1 <- sample(x=c(1, 2, 3, 4, 5, 6), size=1, replace=T, prob=c(1/6, 1/6, 1/6, 1/6, 1/6, 1/6)) 
       tmp2 <- sample(x=c(1, 2, 3, 4, 5, 6), size=1, replace=T, prob=c(1/6, 1/6, 1/6, 1/6, 1/6, 1/6)) 
       sum2 <- tmp1 + tmp2
       if (sum2 == sum) {
         n <- 1
       } else if (sum2 == 7) {
         n <- 0
       }
     }
   }
  result.Vec <- c(result.Vec, n)
}

请参阅下面的问题,我的循环作为参考(不是寻求解决此问题的方法): 骰子游戏掷骰子的玩法如下。玩家掷两个骰子,如果总和是 7 或 11,则她获胜。如果总和是二、三或十二,那么她就输了。如果总和是其他数字,那么她继续投掷,直到她再次投掷该数字(在这种情况下她赢)或她投掷 7(在这种情况下她输了)。根据 1000 次模拟计算玩家获胜的概率。

【问题讨论】:

  • 可能你的while() 被卡住了,因为退出的条件永远不会评估为假。您应该创建一个counter 来限制这种可能性,在每次迭代时更新counter,然后使用if()break 提前退出。
  • 您应该更新您的问题,也许可以解释您要模拟的内容,似乎是某种骰子抽奖..
  • @RLave 感谢您的回复!在代码块下方,我想我包含了我要解决的问题的主体。你看不出来吗?
  • 你的代码没问题,但是while中的条件应该是&而不是|,否则条件总是假的。

标签: r for-loop if-statement while-loop simulation


【解决方案1】:

正如我在评论中提到的,问题仅在于 while 循环中的条件。它应该是 AND 而不是 OR,否则 while 循环将始终失败。我已经对此进行了测试,并且可以正常工作:

result.Vec <- NULL
for (trials in 1:1000) {
  print(trials)
  sum <- 0
  sum2 <- 0
  n <- 0
  tmp1 <- sample(x=c(1, 2, 3, 4, 5, 6), size=1, replace=T, prob=c(1/6, 1/6, 1/6, 1/6, 1/6, 1/6)) 
  tmp2 <- sample(x=c(1, 2, 3, 4, 5, 6), size=1, replace=T, prob=c(1/6, 1/6, 1/6, 1/6, 1/6, 1/6)) 
  sum <- tmp1 + tmp2
  if (sum == 7 | sum == 11) {
    n <- 1
  } else if (sum == 2 | sum == 3 | sum == 12) {
    n <- 0
  } else {
    while (sum2 != sum & sum2 != 7) {
      tmp1 <- sample(x=c(1, 2, 3, 4, 5, 6), size=1, replace=T, prob=c(1/6, 1/6, 1/6, 1/6, 1/6, 1/6)) 
      tmp2 <- sample(x=c(1, 2, 3, 4, 5, 6), size=1, replace=T, prob=c(1/6, 1/6, 1/6, 1/6, 1/6, 1/6)) 
      sum2 <- tmp1 + tmp2
      if (sum2 == sum) {
        n <- 1
      } else if (sum2 == 7) {
        n <- 0
      }
    }
  }
  result.Vec <- c(result.Vec, n)
}

【讨论】:

    【解决方案2】:

    首先,为了加快代码速度,您应该摆脱外部 for 循环。而是使用模拟一个游戏的函数,然后使用replicate 运行游戏n 次。

    其次,使用break 退出while 循环。另外,请注意,将变量命名为 sum 是不明智的,因为已经有一个名为 sum 的 R 函数。

    这是我的代码版本:

    simulate_game <- function(){
    
      tmp1 <- sample(x = 1:6, size = 1) 
      tmp2 <- sample(x = 1:6, size = 1) 
    
      mysum <- tmp1 + tmp2
    
      if (mysum %in% c(7, 11)) {
        n <- 1
      } else if (mysum  %in% c(2, 3, 12)) {
        n <- 0
      } else {
        mysum2 <- 0
    
        while (! mysum2 %in% c(mysum, 7)) {
          tmp1 <- sample(x = 1:6, size = 1) 
          tmp2 <- sample(x = 1:6, size = 1) 
    
          mysum2 <- tmp1 + tmp2
    
          if (mysum2 == mysum) {
            n <- 1; break()
          } else if (mysum2 == 7) {
            n <- 0; break()
          }
        }
      }
    
      return(n)
    }
    

    现在您可以使用以下方法来模拟 1000 次运行:

    set.seed(1)
    table(replicate(1000, simulate_game()))
          0   1 
         530 470
    

    请注意,我使用set.seed 设置了一个随机种子。这使您的结果具有可重复性。

    【讨论】:

    • 不是吗?我不知道。无论如何,当使用复制而不是 for 循环时,我发现代码更易于阅读。
    • 刚查了一下,这种情况下,速度更快。有时不是,例如lapply。无论如何我同意你的看法,它更干净。
    【解决方案3】:

    while 循环卡住了:

    while (sum2 != sum || sum2 != 7)
    

    如果 sum != 7(因此对于几乎任何可能的值),这将始终评估为 TRUE。

    【讨论】:

      猜你喜欢
      • 2021-10-31
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-04-24
      • 1970-01-01
      • 2020-03-01
      • 1970-01-01
      • 2014-02-01
      相关资源
      最近更新 更多