4

I want to do something if there's a 60% chance (only by using Math.random()). For example, a situation where every value in an array has a 60% chance to be set to 1, otherwise 0.

My confusion is whether we should check

if (Math.random() < 0.6) { ... }

or

if (Math.random() <= 0.6) { ... }

My thought is that it should be the first because 0.0 counts as a possible returned value, but I would like to confirm which one I should use and why.

P123
  • 107
  • 1
  • 7

2 Answers2

6

Use the < operator.

While this is a simplification, consider that computers store fractions by adding terms of the form 2−n. Most real numbers can't be represented exactly, and literals like 0.6 are converted to the nearest double value from a finite set.

Likewise, the random() function can't generate real values from a continuous range between zero and one. Instead, it chooses an integer from N elements in the range 0 to N − 1, then divides it by N to yield a (rational) result in the range [0, 1). If you want to satisfy a condition with a probability of P, it should be true for P ⋅ N elements from the set of N possibilties.

Since zero is counted as one of the elements, the maximum result value that should be included is ( P ⋅ N − 1 ) / N. Or, in other words, we should exclude  P ⋅ N / N, i.e., P.

That exclusion of P is what leads to the use of <.

It might be easier to reason about when you consider how you'd use a method like nextInt(), There, the effect of zero on a small range is more obvious, and your expression would clearly use the < operator: current().nextInt(5) < 3. That wouldn't change if you divide the result: current().nextInt(5) / 5.0 < 0.6. The difference between nextInt(5) / 5.0 and random() is only that the latter has many more, much smaller steps between 0 and 1.

I apologize for misleading people with my original answer, and thank the user who straightened me out.

erickson
  • 265,237
  • 58
  • 395
  • 493
  • There is also a "roundabout" way involving `Math.random`: Use the Fast Dice Roller with a bit generator of the form `Math.random() < 0.5 ? 1 : 0` to generate an integer in [0, 100), then check whether that integer is less than 60. See: https://stackoverflow.com/questions/6046918/how-to-generate-a-random-integer-in-the-range-0-n-from-a-stream-of-random-bits/62920514#62920514 – Peter O. Apr 13 '22 at 23:00
4

Use <. If you ever want to set your odds to 0%, then you might change your comparison value to 0. Since Math.random() can return 0, using <= would not result in a 0% chance. As others have noted, the chance of Math.random() generating the exact number you are testing against is extremely low, so for all values other than 0 you will never notice a difference.

MikeFHay
  • 8,562
  • 4
  • 31
  • 52