简体   繁体   English

如果条件一半的时间,则javascript中的for循环会跳过else

[英]for loop in javascript is skipping else if condition half the time

I'm was just fiddling around with javascript and I wrote function using Math.random that I thought would return a coin-flip. 我只是在玩弄javascript,我使用Math.random编写了函数,以为会返回硬币翻转。 Then I was curious so I ran it through a loop to test how often it flips true/false. 然后我很好奇,所以我循环遍历了它,以测试它翻转真假的频率。 I found out my loop is skipping about half of the else if conditions, and was able to verify this by catching them in the errors var. 我发现我的循环跳过了if条件的其他一半,并且能够通过将它们捕获到错误var中来验证这一点。 So, why is it doing this? 那么,为什么要这样做呢?

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)

truths: 500393 alternativetruths: 249580 errors: 250026 真相:500393真相:249580错误:250026

Your code calls game() twice . 您的代码两次调用game() If the first call isn't true , then the second might or might not be true . 如果第一个调用 true ,那么第二个调用可能正确也可能不true

Just call game() once and assign the result to a variable. 只需调用game()一次,然后将结果分配给变量即可。 Don't make explicit comparisons to true and false ; 不要作出明确比较, truefalse ; if statements work off boolean values, and your function already returns one of those. if语句可以处理布尔值,并且您的函数已经返回了其中之一。

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

Because you're calling game twice , and thus getting two different random flags. 因为您两次调用game ,因此会得到两个不同的随机标志。

The minimal change is to remember the number: 最小的更改是记住数字:

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

But a couple of other notes: 但还有其他一些注意事项:

  • If flag is a boolean (and it is, it's the result of the > operator), then if (flag === true) is pointless. 如果flag是一个布尔值(它是>运算符的结果),则if (flag === true)是没有意义的。 Just use if (flag) . 只需使用if (flag) The result of the === operator is a boolean too, so if you don't trust them to be true or false, where do you stop? ===运算符的结果也是一个布尔值,因此,如果您不相信它们是对还是错,那么在哪里停止? :-) if ((flag === true) === true) ? :-) if ((flag === true) === true)
  • Separately, if (flag === false) should just be if (!flag) . 另外, if (flag === false)应该只是if (!flag)
  • If flag is a boolean (and it is), then if you have if (flag) , having else if (!flag) and then else doesn't make any sense. 如果flag是一个布尔值(并且确实是),那么如果您具有if (flag) ,则拥有else if (!flag)else都没有任何意义。 There is no way you'll reach that final else . 有没有办法,你会达到这个最终else Just if (flag) { } else { } is all you need. 只是if (flag) { } else { }就足够了。
  • But , game isn't fair, it has a very slight bias toward returning false . 但是game不公平,它对返回false偏向很小 Remember, the range returned by Math.random() * 10 is 0 to just under 10, so checking for > 5 means you're skipping the midpoint. 请记住, Math.random() * 10返回的范围是0到不到10,所以检查> 5意味着您跳过了中点。 Because you're dealing with very small fractional numbers, you don't notice the bias, but it's there; 因为您要处理的分数非常小,所以您不会注意到偏差,但它确实存在。 it would be more obvious if you rounded to whole numbers, at which point it would be roughly 40%/60% true/false. 如果四舍五入为整数,则更明显,这时大约为40%/ 60%是/否。 You want >= 5 for fair results. 您希望>= 5以获得公平的结果。
  • game can rather moer succinctly be written: return Math.random() >= 0.5; 可以更简洁地编写gamereturn Math.random() >= 0.5; .
  • Because you're not declaring i , you're falling prey to The Horror of Implicit Globals (that's a post on my anemic little blog) . 因为您未声明i ,所以您正在成为“隐式全球性恐怖”的猎物(这是我贫乏的小博客上的帖子) Remember to declare your variables. 请记住声明变量。

Re > vs. >= , here's an example where I've rounded to whole numbers to make the effect clearer: Re > vs. >= ,这是一个示例,其中我四舍五入为整数以使效果更清晰:

 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) + "%)"); } 
 .as-console-wrapper { max-height: 100% !important; } 

You need to assign game to a var before test for its value. 您需要先将游戏分配给var,然后再测试其价值。 Otherwise, everytime yout check the value with game() you will check a new value. 否则,每次您使用game()检查该值时,您都会检查一个新值。 So it can be false at the first check and true at the second and for this reason increment your errors. 因此,第一次检查可能为false,第二次检查为true,因此,您的错误会增加。 Try this: 尝试这个:

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM