When we want a random number that divides a range into equal intervals, we indicate that in the multiplier…
Math.random() => a float
let x = Math.random()
x => { 0 <= x < 1 | x is Real }
let x = Math.random() * 10
x => { 0 <= x < 10 | x is Real }
We still don’t have intervals, though; not until we floor it.
let x = Math.floor(Math.random() * 10)
x => { 0 <= x < 10 | x is Integer }
x => [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
As probability goes, the probability that x will be less than 10 is 1. The probability that x is less than 0 is 0. There is a probability of 0.1 that x is one of the above.
When we round, that probability changes to 10 / 11 that it is less than 10 since rounding allows the outcome to be equal to 10.
let x = Math.round(Math.random() * 10)
x => { 0 <= x <= 10 | x is Integer }
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
It is important that this distinction is clear. Rounding is a usage case that must take into account the upper limit.
We shift the range by using an offset, such as 1 to remove the zero and to include the upper limit when flooring.
let x = Math.floor(Math.random() * 10) + 1
x => { 0 < x <= 10 | x is Integer }
[1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
If we use rounding, then,
[1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11]
floor
is always rounded down to the nearest integer.
round
is only rounded down is Math.random() < 0.5, other it rounds up to the nearest integer.
Rounding is better suited to working with floats that are near approximations, such as currency transactions.
Math.round(7.49) => 7
Math.round(7.50) => 8
If working on a probabilistic scenario, use floor
.
An integer between 15 and 35 inclusive would look like,
Math.floor(Math.random() * (35 - 15)) + 15 + 1