I was learning JavaScript in freecodecamp, Basic JavaScript. In the stage 103/110 there was a task to create a function which takes 2 arguments (minimum value and maximum value) and the function should return a random number between them. The formula was given and I did the task and completed it, but I didn't quite understand why the formula works.
function randomRange(myMin, myMax) {
return Math.floor(Math.random() * (myMax - myMin + 1) + myMin);
}
console.log(randomRange(10, 20))
This is the code.
and this is the formula Math.floor(Math.random()*(max - min + 1) + min
.
Can you please explain the formula and why does this work?
I was learning JavaScript in freecodecamp.org, Basic JavaScript. In the stage 103/110 there was a task to create a function which takes 2 arguments (minimum value and maximum value) and the function should return a random number between them. The formula was given and I did the task and completed it, but I didn't quite understand why the formula works.
function randomRange(myMin, myMax) {
return Math.floor(Math.random() * (myMax - myMin + 1) + myMin);
}
console.log(randomRange(10, 20))
This is the code.
and this is the formula Math.floor(Math.random()*(max - min + 1) + min
.
Can you please explain the formula and why does this work?
3 Answers
Reset to default 10I'll explain this formula:
Math.floor(Math.random() * (myMax - myMin + 1) + myMin);
Say we want a random number from 5-15 (including both 5 and 15 as possible results). Well, we're going to have to work with Math.random(), which only produces values from 0 through approximately 0.99999999999999, so we need to do two tricks to be able to work with this.
The first trick is recognizing that Math.random()'s lowest possible return value is 0, and 0 times anything is 0, so we need to start our range at 0 and adjust to account for this at the end. Instead of calculating 5-15 from the beginning, we recognize that there are 11 values in 5-15 (5, 6, 7, 8, 9, 10, 11, 12, 13, 14, and 15) and count up that many from 0 (0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10) to use 0-10 as our range instead. This is what the myMax - myMin
part of the formula does. It defines our new max as 10. Then, at the end of the calculations, we'll just add 5 back to whatever result we get to make the possible result range change from 0-10 to 5-15. This is what the + myMin
part of the formula does.
The second trick is recognizing that multiplying Math.random() by our new max range of 10 can only give us a result as high as about 9.999999999999 because Math.random() only goes as high as about 0.99999999999 (never actually 1). When we Math.floor() that later to make it an integer, it brings the result down to 9, so we need to add 1 there to make the maximum possible value 10 instead of 9. That's what the + 1
part of the formula does.
Let's finish this off by walking through an example.
Math.random()
can be 0
at lowest and approximately 0.99999999999999
at highest (never 1). Let's just look at what happens with those two cases to see how the range works out.
If we run the case where we've called randomRange(5, 15)
and Math.random()
gives us 0, here's what we end up with:
Math.floor(Math.random() * (myMax - myMin + 1) + myMin);
=
Math.floor(0 * (15 - 5 + 1) + 5);
=
Math.floor(0 * 11 + 5);
=
Math.floor(0 + 5);
=
Math.floor(5);
=
5
So the lowest value possible is 5. If we run the case where we've called randomRange(5, 15)
and Math.random()
gives us 0.99999999999999
, here's what we end up with:
Math.floor(Math.random() * (myMax - myMin + 1) + myMin);
=
Math.floor(0.99999999999999 * (15 - 5 + 1) + 5);
=
Math.floor(0.99999999999999 * 11 + 5);
=
Math.floor(10.9999999999999 + 5);
=
Math.floor(15.9999999999999);
=
15
So the highest value possible is 15.
Math.random() returns a floating point number in the range [0, 0.999999] *(myMax - myMin + 1) returns the integer value
As an example if your random range is randomRange(10, 20),(myMax - myMin + 1) returns the integer value(20-10+1),that means 11.
There are 11 possible integers as (10,11,12,13,14,15,16,17,18,19,20)
*Math.floor(Math.random() * (myMax - myMin + 1)returns the floating point in the range of (0,myMax-myMin+1)
(0.99999999999999 * (20 - 10 + 1))=10.99999999999
*Therefore we add myMin to get the floating point numbers in the range of(myMin,myMax+1)
(0.99999999999999 * (20 - 10 + 1)+10)=20.99999999999
*Finally, by applying Math.floor() rounds the number DOWN to the nearest integer as 20
Step by step:
Math.random()
returns a floating point number in the range [0, 1), i.e. 0 is a possible outcome, but 1 isn't.(myMax - myMin + 1)
is an integer that represents the number of possible distinct integers you can get as final result.Math.floor(Math.random() * (myMax - myMin + 1)
is therefore a floating point in the range [0,myMax
-myMin
+ 1)By adding
myMin
to that, you get a floating point in the range [myMin
,myMax
+ 1)Finally, by applying
Math.floor()
, the possible values are restricted to integers in the range [myMin
,myMax
+ 1), which for integers is equivalent to {myMin
...myMax
}.
Math.floor(Math.random() * X)
works? – Bergi Commented Jul 19, 2020 at 13:51+1
makes no sense and should be omitted, it is just about including the value ofmax
in the range instead of excluding it. Regarding themin
, it's just a different linear transformation:Math.random()
has range[0,1)
, we want[min,max)
(or[min,max+1)
=[min,max]
) – Bergi Commented Jul 19, 2020 at 13:55+1
, you will have to callrandomRange(10, 21)
if you want an 1/11th chance to get a20
back, which is usually more sensible to reason about – Bergi Commented Jul 19, 2020 at 13:58+1
. Actually it is less confusing now. Let me try the math myself. I might figure it out – an4s911 Commented Jul 19, 2020 at 13:59