Simple question, but I'm interested in the nuances here.
I'm generating random booleans using the following method I came up with myself:
const rand = Boolean(Math.round(Math.random()));
Whenever random()
shows up, it seems there's always a pitfall - it's not truly random, it's compromised by something or other, etc. So, I'd like to know:
a) Is the above the best-practice way to do it?
b) Am I overthinking things?
c) Am I underthinking things?
d) Is there a better/faster/elegant-er way I don't know of?
(Also somewhat interested if B and C are mutually exclusive.)
Update
If it makes a difference, I'm using this for movement of an AI character.
Technically, the code looks fine, but just a bit too complex.
You can compare "Math.random()" to "0.5" directly, as the range of Math.random() is [0, 1). You can divide the range into [0, 0.5) and [0.5, 1).
var random_boolean = Math.random() >= 0.5;
// Example
console.log(Math.random() >= 0.1) // %90 probability of get "true"
console.log(Math.random() >= 0.4) // %60 probability of get "true"
console.log(Math.random() >= 0.5) // %50 probability of get "true"
console.log(Math.random() >= 0.8) // %20 probability of get "true"
console.log(Math.random() >= 0.9) // %10 probability of get "true"
If your project has lodash
then you can:
_.sample([true, false])
For a more cryptographically secure value, you can use crypto.getRandomValues
in modern browsers.
Sample:
var randomBool = (function() {
var a = new Uint8Array(1);
return function() {
crypto.getRandomValues(a);
return a[0] > 127;
};
})();
var trues = 0;
var falses = 0;
for (var i = 0; i < 255; i++) {
if (randomBool()) {
trues++;
}
else {
falses++;
}
}
document.body.innerText = 'true: ' + trues + ', false: ' + falses;
Note that the crypto
object is a DOM API, so it's not available in Node, but there is a similar API for Node.
!Math.round(Math.random());
How about this one?
return Math.round((Math.random() * 1) + 0) === 0;
Answer of Alexander O'Mara
just adding node code snippet
const crypto = require('crypto');
const randomBool = (function () {
let a = new Uint8Array(1);
return function () {
crypto.randomFillSync(a);
return a[0] > 127;
};
})();
let trues = 0;
let falses = 0;
for (let i = 0; i < 100; i++) {
if (randomBool()) {
trues++;
}
else {
falses++;
}
}
console.log('true: ' + trues + ', false: ' + falses);