252

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.

Ben
  • 54,723
  • 49
  • 178
  • 224

10 Answers10

636

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
Vic Seedoubleyew
  • 9,888
  • 6
  • 55
  • 76
CY_
  • 7,170
  • 1
  • 15
  • 26
  • 15
    I like this one solution, as it allows you to tweak the probability of true/false – Evanion Jan 14 '19 at 23:10
  • if you change the number 0.5 to 0.9 for instance, does this increase the probability of false, and how? – Agent Zebra Feb 04 '19 at 23:37
  • if you change it from 0.5 to 0.9. Then, the probability is likely to be changed. I think you can try it with a large number of random loop, like 10000 iterations. – CY_ Mar 07 '19 at 08:19
  • For modern JavaScript you should use `let` i.e. `let randomBool = Math.random() >= 0.5;` – Chris Halcrow Jun 23 '20 at 02:23
  • 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. – Aaron Plocharczyk Aug 04 '20 at 05:07
  • 2
    I modified the answer to use the `<=` operator instead of `>=` to make the answer more intuitive. – Daniel Tonon Nov 09 '20 at 05: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 Nov 25 '20 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 `<`. – Aaron Plocharczyk Nov 25 '20 at 20:37
  • I like the thought process used in arriving at the solution – mykoman Mar 05 '21 at 06:54
  • Doesn't seem trustworthy, got all trues on the first run. – DaCuteRaccoon May 19 '22 at 16:23
  • this is how casinos set up their machines 80% to the house ;) – JesseBoyd Jun 01 '23 at 22:05
38

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.

Alexander O'Mara
  • 58,688
  • 18
  • 163
  • 171
  • 4
    `Math.random()` is notoriously un-random in many ways, great alternate suggestion – Charles Harris Aug 16 '16 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) – Amund Midtskog Jun 05 '17 at 08:33
  • 2
    @AmundMidtskog Good call. I should have typed: `a[0] > 127` – Alexander O'Mara Jun 05 '17 at 08: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 Nov 11 '17 at 06:24
16
!Math.round(Math.random());

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

Nato Boram
  • 4,083
  • 6
  • 28
  • 58
user12066722
  • 281
  • 3
  • 3
  • 12
    Please format this more helpfully (https://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 Sep 14 '19 at 10:54
  • above comment is not helpful. – Trevor Blythe Dec 30 '21 at 16:23
  • So simple!!! Perfect!!! – Ole Jun 22 '23 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 >=;

Arthur Khazbs
  • 705
  • 8
  • 19
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.

LeonNikolai
  • 112
  • 1
  • 5
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() );
sheriffderek
  • 8,848
  • 6
  • 43
  • 70
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)
Rishu Singh
  • 11
  • 1
  • 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](/help/how-to-answer). – Community May 08 '22 at 04: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 Dec 05 '22 at 06:40
1

My way :)

Math.floor(Math.random() * 100 ) % 2 === 1
  • 2
    While this code may solve the question, [including an explanation](//meta.stackexchange.com/q/114762) 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 May 27 '23 at 09:16
-1

How about this one?

return Math.round((Math.random() * 1) + 0) === 0;
Alex
  • 624
  • 1
  • 9
  • 12