269

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.

5
  • 63
    const rand = Math.random() < 0.5 is equivalent and simpler.
    – Hamms
    Commented Apr 20, 2016 at 22:32
  • 1
    Nothing is actually random, the goal is to get as close to random as possible. Commented Apr 20, 2016 at 22:34
  • 2
    And if you have a 50/50 chance,math.random should be plenty. Just use milliseconds for your seed. Commented Apr 20, 2016 at 22:37
  • I think it's pretty random the time one visits a website :D so I had this idea... Boolean(+Date.now()%2) Commented Apr 20, 2016 at 22:38
  • With lodash - !!_.random(1)
    – vsync
    Commented Nov 6, 2016 at 15:17

10 Answers 10

668

You can compare Math.random() to 0.5 directly, as the range of Math.random() is [0, 1) (this means 'in the range 0 to 1 including 0, but not 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); //10% probability of getting true
console.log(Math.random() < 0.4); //40% probability of getting true
console.log(Math.random() < 0.5); //50% probability of getting true
console.log(Math.random() < 0.8); //80% probability of getting true
console.log(Math.random() < 0.9); //90% probability of getting true

11
  • 17
    I like this one solution, as it allows you to tweak the probability of true/false
    – Evanion
    Commented Jan 14, 2019 at 23:10
  • 10
    Why not use just < instead of >=? Math.random() < 0.5 is exclusive of 0.5 for the low half and exclusive of 1 for the high half- so it's still exactly a 50% chance. Plus, it's shorter. And in my opinion, Math.random() < 0.1 is more intuitive to read as "10% chance of true" than Math.random() >= 0.9. I guess that's being pretty picky though. Nice answer. Commented Aug 4, 2020 at 5:07
  • 2
    I modified the answer to use the <= operator instead of >= to make the answer more intuitive. Commented Nov 9, 2020 at 5:45
  • 2
    Isn't the answer now semantically wrong? As @Aaron Plocharczyk described, shouldn't the 0.5 belong to the probability of the upper half? 0.0 belongs to the lower half and 1.0 is not in the [0,1) range of Math-random(). So please change the <= to <.
    – bjrne
    Commented Nov 25, 2020 at 19:51
  • 3
    @bjrne You are correct; the last person that edited this answer made that mistake. I went ahead and updated the answer to reflect your suggestion and veer away from >= in favor of <. Commented Nov 25, 2020 at 20:37
37

If your project has lodash then you can:

_.sample([true, false])

Alternatively you can use your own sample function (source):

const sample = arr => arr[Math.floor(Math.random() * arr.length)];
18

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
  • 4
    Math.random() is notoriously un-random in many ways, great alternate suggestion Commented Aug 16, 2016 at 19:38
  • 3
    I'm just gonna add a small correction here, as I discovered after 50 000 000 runs that it generated on average 0.78% or so more zeroes: return a[0] <= 127; (Else 127 is never included) Commented Jun 5, 2017 at 8:33
  • 2
    @AmundMidtskog Good call. I should have typed: a[0] > 127 Commented Jun 5, 2017 at 8:39
  • 1
    By the way, you may usually want to generate a much larger number of samples than just 255. Rather, in order to reduce the noise in the data, something like 100,000 – or even tens of millions, as suggested in the other comment, if you want to see errors as small as 0.78%.
    – caw
    Commented Nov 11, 2017 at 6:24
16
!Math.round(Math.random());

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

3
  • 13
    Please format this more helpfully (stackoverflow.com/editing-help) and add some explanation. Code-only answers are not very much appreciated. Adding an explanation would help fighting the misconception that StackOverflow is a free code-writing service.
    – Yunnosch
    Commented Sep 14, 2019 at 10:54
  • above comment is not helpful. Commented Dec 30, 2021 at 16:23
  • So simple!!! Perfect!!!
    – Ole
    Commented Jun 22, 2023 at 13:29
14

Impressed a lot by Kelvin's answer I would like to suggest a fairly similar but slightly enhanced solution.

var randomBoolean = Math.random() < 0.5;

This solution is a bit more obvious to read, because the number on the right-hand side of < tells you the probability of getting true rather than of getting false, which is more natural to comprehend. Also < is one symbol shorter than >=;

1
  • The answer I was referring to has been updated and now suggests using < as well Commented Jul 18, 2022 at 14:00
3

Potentialy faster solutions...

Bitwise operator approach i just thought of Math.random() + .5 >> 0 or ~~(Math.random() + .5). Here is a performance test to judge for yourself.

let randomBoolean = Math.random() + .5 >> 0;                 //chance of true
const randomBoolean = chance => Math.random() + chance >> 0; //chance of true

The bitwise operators is in this case essentially just the same as using Math.trunc() or Math.floor(), therefore this is also posible Math.trunc(Math.random() + .5).

let randomBoolean = Math.trunc(Math.random() + .5);
const randomBoolean = chance => Math.trunc(Math.random() + chance);

Other more common solutions

The more readable and common way to get random boolean is probably a comparative approach like Math.random() >= .5 from Kelvin's answer or Math.random() < .5; from Arthur Khazbs's answer, they actualy output true & false, and not 1 & 0.

let randomBoolean = Math.random() >= .5;                 //chance of false
const randomBoolean = chance => Math.random() >= chance; //chance of false

let randomBoolean = Math.random()  < .5;                 //chance of true
const randomBoolean = chance => Math.random() < chance;  //chance of true

The only reason to use the Math.round(Math.random()) approach is simplicity.

1
  • 2
    I'm not sure if this is worth pointing out, but (.49999999999999997 >= .5) != (.49999999999999997+ .5 >> 0) Commented Aug 4, 2020 at 5:26
2

Sometimes I just need a "random" boolean for a teaching example or something. Depending on your use-case, this might be random enough.

function flipCoin() {
  return Boolean(Date.now() % 2);
}

console.log( flipCoin() );

2

My way :)

Math.floor(Math.random() * 100 ) % 2 === 1
1
  • 2
    While this code may solve the question, including an explanation of how and why this solves the problem would really help to improve the quality of your post, and probably result in more up-votes. Remember that you are answering the question for readers in the future, not just the person asking now. Please edit your answer to add explanations and give an indication of what limitations and assumptions apply.
    – Yunnosch
    Commented May 27, 2023 at 9:16
1

let try most easy solutions

 let status=Math.round(Math.random())
 console.log(status)
 if(status==1)
 {
 status=true
 }else{
 status=false
 }
 console.log(status)

2
  • 2
    Your answer could be improved with additional supporting information. Please edit to add further details, such as citations or documentation, so that others can confirm that your answer is correct. You can find more information on how to write good answers in the help center.
    – Community Bot
    Commented May 8, 2022 at 4:42
  • It is pointless and verbose to use an if/else when you are testing a boolean value. It is also not recommended to use == when you know it is a number. Use === let status = Math.round(Math.random()) === 1; is much shorter, but not a better random than the excepted answer
    – mplungjan
    Commented Dec 5, 2022 at 6:40
-1

How about this one?

return Math.round((Math.random() * 1) + 0) === 0;
2
  • 1
    OP states that he already uses similar methods, no need to post this. Commented Jul 29, 2018 at 2:34
  • 1
    why do you multiply it by one? Commented Dec 30, 2021 at 16:24

Not the answer you're looking for? Browse other questions tagged or ask your own question.