I'm was just fiddling around with javascript and I wrote function using Math.random that I thought would return a coin-flip. 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. 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
Your code calls game()
twice . If the first call isn't true
, then the second might or might not be true
.
Just call game()
once and assign the result to a variable. Don't make explicit comparisons to true
and false
; if
statements work off boolean values, and your function already returns one of those.
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.
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:
flag
is a boolean (and it is, it's the result of the >
operator), then if (flag === true)
is pointless. Just use 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 === false)
should just be if (!flag)
. 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. There is no way you'll reach that final else
. Just if (flag) { } else { }
is all you need. game
isn't fair, it has a very slight bias toward returning 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. 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. You want >= 5
for fair results. game
can rather moer succinctly be written: return Math.random() >= 0.5;
. i
, you're falling prey to The Horror of Implicit Globals (that's a post on my anemic little blog) . Remember to declare your variables. Re >
vs. >=
, here's an example where I've rounded to whole numbers to make the effect clearer:
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. Otherwise, everytime yout check the value with game() you will check a new value. So it can be false at the first check and true at the second and for this reason increment your errors. Try this:
for(i=0;i<999999;i++) {
let gameResult = game();
if (gameResult === true) {
truths++
} else if (gameResult === false) {
alternativetruths++
} else {
errors++
}
}
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.