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) Creating Reusable Code with Functions Random Number Challenge Solution

Despite how hard I try, I just don't understand the placement of the upper and lower parameters in the math equation.

It was a bit frustrating to hear that "this challenge should've been easy". That's probably not the best way to open a tutorial. I partially agree, though - writing out the actual function was pretty easy. Knowing where to place the upper and lower parameters and why is proving very difficult for me to comprehend.

Any help would be great.

Thanks!

2 Answers

Gavin Ralston
Gavin Ralston
28,770 Points

Here's an attempt to work this out by plugging in values in place of the variables to see if it makes a little more sense:

Say we're looking for values between 3 and 7 to show up:

This will get me a result between 0.0000 and .9999999 (or a percentage of our "progress" from the beginning of the range (at 0%) to the end of our range (at 99.99% -- and this, precisely, is why we'll need to use a +1 in our formula later)

Math.random();

/* Possible results
0.02982171392068267      nearly 30% of the "way through" our range of results
0.034872065065428615  nearly 35% of the way through
0.8328706363681704       around 83% of the way through
0.6632871513720602         around 66% of the way through
*/

So we need to use that percentage we got and multiply our range of results by that number to figure out where we "land" in the set of results we want. So for instance, if I wanted a range of numbers between 3 and 7, I would do this:

(7 - 3) = 4 which is as good a starting point as any I suppose, to get a "percentage of progress through the range of 3-7

Math.random() * (7-3);

/* Possible results:
0.11195843759924173
1.4768482884392142
3.3396804742515087
1.6203259713947773
3.579301442950964
*/

But wait, we want numbers between 3 and 7 not from 0 to almost 4...

So after we calculate where we'd "land" in a range of numbers of a certain size (above) now we just tell the formula where we wanted to start from. We bump the "range" of answers from 0.00-3.99 up by the value of our starting point (min) like so:

Math.random() * (7 - 3) + 3;

/* Possible results from above would now look like THIS::
0.11195843759924173 + 3 = 3.11195843759924173
1.4768482884392142 + 3 = 4.4768482884392142
3.3396804742515087 + 3 = 6.3396804742515087
1.6203259713947773 + 3 = 4.6203259713947773
3.579301442950964 + 3 = 6.579301442950964
*/

But wait, we want INTEGERS, not messy floating point numbers, right?

Hello, Math.floor() -- This will just cut off the results and leave us with the numbers we want:

Math.floor(Math.random() * (7 - 3)) + 3 ;
/* Possible results from above would now look like THIS::
3.11195843759924173 = 3
4.4768482884392142 = 4
6.3396804742515087 = 6
4.6203259713947773 = 4
6.579301442950964 = 6
*/

Awesome, integer results like we wanted.

But wait, we want FIVE possible results, right? 3, 4, 5, 6, or 7

Well, that's where the tricky part is. Remember that range we calculated earlier? 7 - 3 = 4. so that,'ll get us 3, 4, 5, and 6, but in order to include the number 7 in our result, we need to make that range just one number bigger.

Gotta follow the order of operations, so you have to force all that addition to happen first before Math.random() gets its hands on the value. So (max - min + 1) or in our case (7 - 3 + 1) needs to be shoved into parenthesis.

Math.floor(Math.random() * (7- 3+ 1)) + 3;

What's going on here is just watching the parenthetical stuff and seeing what calculation happens where:

Method calls happen inside-to-outside, so all the inner stuff is resolved first. So INSIDE Math.floor() this is going on:

Math.random() happens first, giving us a 0.00 - 0.99 "percentage travelled through the range" (7 - 3 + 1) happens and gives us a range of FIVE numbers. 7 - 3 + 1 = 5

remember 7 and 3 are variables max and min, we just plugged the values in, the +1 is a constant value to ensure that the range is always big enough to cover the min and the max value.

So we're looking at a progress of steps like this inside the machine as it calculates one tiny bit at a time:

// start here, trying to get a range from 3 to 7
Math.floor(Math.random() * (7- 3+ 1)) + 3;

// then becomes
Math.floor(Math.random() * 5) + 3;

// Which might just become
javascript
Math.floor(1.4768482884392142 + 3);

// which would become
Math.floor(4.4768482884392142);

//which is truncated and turned into an integer
4

So after this vomitous post, the tl;dr is:

  • Calculate the size of the range (min - max) + 1
  • Multiply it by the results of Math.random to get the "percentage progress through the range"
  • Because your results will start at zero, add the min value to any result so it'll start at the right spot
  • Round off the decimals, which you don't need once you're done.
Joey McGuire
Joey McGuire
3,188 Points

Hey Gavin, I was having a bit of a problem understanding the math behind this equation myself. Your explanation is the best I've found. Thanks so much for your help!

C. Kattenberg
C. Kattenberg
3,652 Points

Hey Daniël,

A bit of a late reply, maybe this will help:

function getRandomNumber( lower, upper ) {
    Math.floor(Math.random() * (upper - lower +1)) + lower;
}

The "lower" that is added at the end makes sure that even if

Math.floor(Math.random() * (upper - lower +1))

amounts to absolute 0 (which will be the case if Math.random generates a 0), the eventual number will still be at least the lower value.

Upper is the maximum value, and since the lower value is added at the end, this first part of the function:

Math.floor(Math.random() * (upper - lower +1))

should generate a number between 0 and (upper - lower), because "(upper - lower) + lower" will amount to the upper value. For example, if upper = 100 and lower = 10: (100 - 10) + 10 = 100

In this case, we want "Math.floor(Math.random() * (upper - lower +1))" to generate a number between 0 and 90, so the eventual outcome, after adding the lower value, will be a number between 10 and 100.

To ensure that, we want this part:

Math.random() * (upper - lower +1)

To generate a number between 0 and 90.99999999999999, because the numbers are rounded down by Math.floor(). If the 1 wasn't added, the number could never be 90 or higher, because Math.random() never generates a 1.