Welcome to the Treehouse Community

Want to collaborate on code errors? Have bugs you need feedback on? Looking for an extra set of eyes on your latest project? Get support with fellow developers, designers, and programmers of all backgrounds and skill levels here with the Treehouse Community! While you're at it, check out some resources Treehouse students have shared here.

Looking to learn something new?

Treehouse offers a seven day free trial for new students. Get access to thousands of hours of content and join thousands of Treehouse students and alumni in the community today.

Start your free trial

JavaScript JavaScript Basics (Retired) Working With Numbers The Random Challenge Solution

Travis Gregory
Travis Gregory
960 Points

My code works but I don't understand the math.

My code works but after I ran it through some tests I'm confused about the math. In my code it doesn't seem to matter if I put the larger number in first or second in my prompts. Either way I get a random number within the provided range. My code is below.

var inputOne = prompt("Please enter your first number here");
var inputTwo = prompt("Please enter your second number here");
var userNumberOne = parseInt(inputOne);
var userNumberTwo = parseInt(inputTwo);
var randomNumber = Math.floor(Math.random() * (userNumberOne - userNumberTwo + 1)) + userNumberTwo;
document.write("Great! " + randomNumber + " is a number between " + userNumberOne + " and " + userNumberTwo + "!");

2 Answers

Daniel Gauthier
Daniel Gauthier
15,000 Points

Hey Travis,

The nature of the formula used in this process will ensure that you always get a number between the low range and the high range provided, regardless of how you enter the numbers.

To demonstrate, here are a few test cases.

Test 1

Let's say we enter 5 as userNumberOne and 2 as userNumberTwo. Using the formula provided:

Math.floor(Math.random() * (userNumberOne - userNumberTwo + 1)) + userNumberTwo;

Let's assume Math.random() gives us a value of 0.5 to keep this example simple. The math would then be:

  1. 5 - 2 = 3
  2. 3 + 1 = 4
  3. 0.5 * 4 = 2
  4. Math.floor would keep the value of 2 as 2.
  5. 2 + 2 = 4

4 is in between the upper and lower range.

Now let's use a wider range example.

Test 2

Our new numbers will be userNumberOne(100) and userNumberTwo(1), with a Math.random() result of 0.358.

  1. 100 - 1 = 99
  2. 99 + 1 = 100
  3. 0.358 * 100 = 35.8
  4. Math.floor will cut 35.8 to 35.
  5. 35 + 1 = 36

36 is within the upper and lower range.

To really understand why this works, let's do one last test using the same numbers, but reversing the first and last numbers entered by the user.

Test 3

Our new numbers will be userNumberOne(1) and userNumberTwo(100), with a Math.random() result of .358.

  1. 1 - 100 = -99
  2. -99 + 1 = -98
  3. 0.358 * -98 = -35.084
  4. Math.floor will cut -35.084 to -36.
  5. -36 + 100 = 64

64 is within the upper and lower range.

The reason the formula works both ways is mainly due to the addition of the second number as the final part of the formula. By writing the formula in the way it's presented, the number generated will always fall within the range of the two numbers provided, even if you supply a negative number for one or both of the inputs.

Good luck with the course!

Travis Gregory
Travis Gregory
960 Points

Thanks for clarifying that for me Daniel! You couldn't have been any clearer.

Steven Parker
Steven Parker
231,007 Points

:x: Close, but you did not account for the fact that the range will differ depending on the number order.
:point_right: It does matter if you put the larger number in first or second.

I think there's 2 important differences when you get the order of the numbers reversed.

You can no longer get the lower number and the higher number will be extremely rare.

So it reduces the range by 1 and creates an unequal distribution of the remaining numbers.

Steven Parker
Steven Parker
231,007 Points

While producing the higher number might be possible on some browsers, it will not be on all. And even where it is possible, the probability is so small that the evenness of the distribution on the other numbers will not be significantly affected. See the other comment after my answer for some actual test statistics.

smriti chawla
smriti chawla
2,566 Points

Even I was confused about the math here, I think the trick here is to remember this when creating a formula:

0.999 = highest value you can get for math.random()

Now multiple this by any number:

0.999 X 5 = 4.99 0.999 X 9 = 8.99 0.999 X 2 = 1.99

Notice the pattern in the outcome? This mainly comes down to this: (user input number - 1) + 0.99. Remembering this will help you calculate the higher range and formulate math solutions easily with Math.random().

Hope this helps.

Steven Parker
Steven Parker
231,007 Points

:point_right: The order does matter — one way is inclusive, the other exclusive.

If you put the larger number in first, you multiply random() by the range and then add the lower number, this is the conventional method and will generate values between (inclusive) the two numbers.

But when you put the smaller number first, you multiply by a negative number that is smaller than the range and then add the larger number, which will generate values between but EXCLUDING the numbers entered.

Examples:

  • if you put in 5 and then 2, you will get an even distribution of 2, 3, 4 and 5
  • if you put in 2 and then 5, you will get an even distribution of 3 and 4

Note that in the second case you might also see an extremely rare 5 - thanks Jason!

From a UX standpoint, users are probably accustomed to making a range choice lowest-first and having the range be inclusive. If you prefer it to work the other way, and/or you want to give the user the choice between inclusive and exclusive, be sure to provide explicit instructions explaining how it works to avoid confusion.

In the case of 2 then 5, you can get back 3, 4, and 5. Although it will be rare to get a 5. You would get it when Math.random() returns a 0.

Steven Parker
Steven Parker
231,007 Points

"Rare" is a bit of an understatement. Although random() is defined to return a range inclusive of 0, true zero may or may not occur at all in a given JavaScript engine. In an actual test, where a billion random numbers were generated and tested against a min and max, Chrome returned zero 12 times, Safari twice, and no other browser generated anything smaller than 4.0e-10. So the chances of getting 0 are at best statistically negligible.

I agree with you that it's not going to be very likely to come out.

I was only trying to point out that we should be aware of the possibility and plan for it in our code.

Steven Parker
Steven Parker
231,007 Points

The analysis was provided only for understanding what the code provided actually does now.

For planning purposes, I would recommend sticking to the conventional method of "random * range + offset" with a positive range. If the inclusive/exclusive choice is actually intended to be offered based on number entry order, this could be coded for explicitly using a positive range in either case. And if that choice is not intentional, the code can also be enhanced to provide the desired behavior regardless of entry order.