如果条件有一半时间,javascript中的for循环正在跳过其他

时间:2017-01-31 15:35:21

标签: javascript

我只是在摆弄javascript而且我使用Math.random编写了函数,我认为它会返回一个硬币翻转。然后我很好奇,所以我通过一个循环来测试它翻转true / false的频率。我发现我的循环正在跳过大约一半的其他条件,并且能够通过在错误var中捕获它们来验证这一点。那么,为什么要这样做呢?

var truths = 0;
var alternativetruths = 0;
var errors = 0;

function game() {
  var score = Math.random()*10;
  return score>5;
}

for(i=0;i<999999;i++) {
  if (game() === true) {
    truths++
  } else if (game() === false) {
    alternativetruths++
  } else {
    errors++
  }
}
console.log("truths:",truths,"alternativetruths:",alternativetruths,"errors:",errors)

真理:500393 alternativetruths:249580错误:250026

3 个答案:

答案 0 :(得分:9)

您的代码调用game() 两次。如果第一个电话不是 true,那么第二个电话可能是true,也可能不是。{/ p>

只需拨打game()一次,然后将结果分配给变量即可。不要与truefalse进行明确比较; if语句可以解决布尔值,并且您的函数已经返回其中一个。

for (var i = 0; i < 999999; i++) {
  var result = game();
  if (result)
    truths++;
  else
    alternativetruths++;
}

答案 1 :(得分:3)

因为您正在调用game 两次,因此会获得两个不同的随机标记。

最小的变化是记住数字:

for(i=0;i<999999;i++) {
  var flag = game();
  if (flag === true) {
    truths++
  } else if (flag === false) {
    alternativetruths++
  } else {
    errors++
  }
}

但其他一些说明:

  • 如果flag是布尔值(并且它是>运算符的结果),则if (flag === true)毫无意义。只需使用if (flag)即可。 ===运算符的结果也是布尔值,所以如果你不相信它们是真或假,你在哪里停止? :-) if ((flag === true) === true)
  • 另外,if (flag === false)应为if (!flag)
  • 如果flag是布尔值(并且是),那么如果您有if (flag),则else if (!flag)然后else没有任何意义。您无法达到最终else。只需if (flag) { } else { }即可。
  • 但是game并不公平,它有 非常轻微 偏向返回{{1} }。请注意,false返回的范围为Math.random() * 10,不到10,因此检查0表示您正在跳过中点。因为你处理的是非常小的分数,所以你没有注意到这种偏见,但它就在那里;如果你四舍五入到整数,这将是更明显的,在这一点上它将是大约40%/ 60%真/假。您希望> 5获得公​​平的结果。
  • >= 5可以简洁地写成:game
  • 因为您未声明return Math.random() >= 0.5;,所以您会成为The Horror of Implicit Globals 的牺牲品(我的贫血小博客上的帖子) 。记得声明你的变量。

重新i>,这里有一个例子,我将四舍五入到整数以使效果更清晰:

&#13;
&#13;
>=
&#13;
for (var n = 0; n < 4; ++n) {
  setTimeout(test.bind(null, n, true), 200 * n);
  setTimeout(test.bind(null, n, false), 200 * n + 100);
}
function test(num, gte) {
  var truths = 0;
  var alternativetruths = 0;
  var errors = 0;

  function game() {
    var score = Math.floor(Math.random() * 10);
    return gte ? score >= 5 : score > 5;
  }

  for (var i = 0; i < 999999; i++) {
    var flag = game();
    if (flag) {
      truths++;
    } else {
      alternativetruths++;
    }
  }
  showStats(num, gte, truths, alternativetruths);
}
function showStats(num, gte, truths, alternativetruths) {
  var total = truths + alternativetruths; // Should be 999999 of course
  var truthsPercent = (truths * 100) / total;
  var altPercent = (alternativetruths * 100) / total;
  console.log(num, gte ? ">=" : ">", "truths:", truths, "alternativetruths:", alternativetruths, "(" + truthsPercent.toFixed(2) + "% vs. " + altPercent.toFixed(2) + "%)");
}
&#13;
&#13;
&#13;

答案 2 :(得分:0)

您需要在测试前为游戏分配游戏的值。否则,每次使用game()检查值时,您都会检查一个新值。所以在第一次检查时它可能是假的,在第二次检查时可能是真的,因此增加了你的错误。 试试这个:

for(i=0;i<999999;i++) {
  let gameResult = game();
  if (gameResult === true) {
    truths++
  } else if (gameResult === false) {
    alternativetruths++
  } else {
    errors++
  }
}