JS generate random boolean

2020-02-17 04:59发布

问题:

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.

回答1:

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"



回答2:

If your project has lodash then you can:

_.sample([true, false])


回答3:

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.



回答4:

!Math.round(Math.random());

­­­­­­­­­­­­­­



回答5:

How about this one?

return Math.round((Math.random() * 1) + 0) === 0;


回答6:

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);