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

Amber Touch
Amber Touch
2,339 Points

Should be easy? already learned??? The math is perplexing

I'm really not sure why Dave said this should have been easy. That is discouraging to the large numbers of people who struggled. Also, this claim that we already learned how to do this earlier in the course had me (and several previous users) scratching temples in utter confusion.

I've read through the earlier comments, and when people put links to other resources to explain, I feel like those explanations are even harder than the original video to understand. It's not that I'm not trying, but boy is this hard.

Can someone please explain using common English for normies, and NOT Mozilla Developer Network that was written for people with a PhD in CompSci, how the math is arrived at? I have watched again and again but I don't understand. Why are we subtracting then adding, and adding again??? What?

I can see why so many people give up on learning to code.

agree!

11 Answers

Erik Nuber
Erik Nuber
20,629 Points

Really want to try again. I think you can get this.

forget the multiplication and addition.

Math.random()

This will give you a number from and including 0 up to 1 but not including one. That is a huge amount of numbers from 0 up to 0.99999999999999 etc.

when you call this function it gives you just a single number thats it.

by itself that isn't overly useful. So lets imagine we have a single die that is eight sided. We now need a number that can range from 1 to 8. Since a die roll is random, we have to use the random number generator.

The question is how do we create a random number between those two digits.

We know that Math.random() can return a 0 and we know at most it can return .9999999 repeating. A 0 is useless to us so right off the bat, in order to get a number within our range we will have to add a one in. This is so that on the chance Math.random() gives us a 0 we can still achieve our baseline of 1. so here is where we are at right now

Math.random() + 1

so now I will get a random Number between 1 and 1.999999 repeating.

If I multiply those by 8 which is the number that matches our highest number on the 8-sided die. I would get a number from 8 to 15.99992. So we can't do it this way

(Math.random() +1) * 8

So we have to see what else makes sense. Going back to just our Math.random() giving us a number from 0 to 0.999999 and multiplying that by the highest digit on our 8-sided die we would then get 8 * 0 = 0 and 8 * .99999 = 7.999992

so we have

Math.random() * 8

This puts us now in a range we are comfortable with we are almost there we now have a number from 0 to 7.99992 which is virtually 8. However, we have the problem that we have a 0 as our base and, we are almost to but not quite to our top number of 8.

We already know we should be adding in one so lets do that next.

(Math.random() * 8) + 1

This will give you now a number from 1 to 8.999992. That puts us to almost the correct answer yet again. We now have met our objective to be between 1 and some number. However we are farther away on the opposite end. We are almost to 9.

This is where Math.floor() comes in. It does the opposite of Math.ceil(). It will take any number and round it down to the nearest whole number. 124.89673453453534234324245 is still 124 with Math.floor(). So this is now useful for us because you need to get that 8.99992 down to a whole number.

Math.floor(Math.random() * 8) + 1

If you get this, please let me know and I will move on to upper and lower etc....

Amber Touch
Amber Touch
2,339 Points

Yes, this makes sense so far! thanks so much for explaining it so clearly!

Erik Nuber
Erik Nuber
20,629 Points

Ok, then lets move on to upper and lower.

You know know how to get any random number from 1 to whatever it is. We just replace 8 with the number we want to go up to. Lets call it upper.

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

This has done nothing to what we had before but change 8 to some number we want to use as the largest whole number we want to get a random number to.

This can be very handy, you could even get a random number from 0 to Upper - 1 now by not having the + 1 there.

Math.floor(Math.random() * upper)

The only difference here is we are now not adding in that one. So we will get a random number from 0 to upper-1. Remember that with our die roll of an 8 sided die, before we added the 1 back into the equation we had 0 up to the largest number of 7.99992. So when we use Math.floor we will now get a number between 0 and 7. So now you have two random numbers you know how to achieve with a very simple formula


So now we need to think about how to achieve a number outside of that range. Let say we take the same 8 sided die. Someone rubbed the one off and, another person came along and wrote 9 on it so now the die can roll a number between 2 and 9. Great, our random number formula won't work anymore. How do we now achieve that.

Well, we now have to deal with an upper number and a lower number. Our upper will be 9 now and our lower will be two so lets plug it in starting with what we know already

Math.floor(Math.random() * 9) + 1

This will give you a random number of 1 - 9, which is not what we are looking for. You can't just add in another one to get the low in to two because then we would generate a random number from 2 - 10. So if we take the upper number and subtract out the lower number we end up with 7 in our case.

Math.floor(Math.random() * (9-2))+1

This gives us a random number from 1 to 7. so now we have to figure out how to figure out the best way to get what we are looking for 2-9. If we add in a one to this outside of our formula as we did again so we have

Math.floor(Math.random() * (9-2)) + 1 + 1

We would end up with a random number from 2 to 8. So that doesn't work. Lets try adding one into it before we do the multiplication

Math.floor(Math.random() * (9-2) +1) + 1;

Now we get a random number from 1 to 8. We are back to where we started and, we made the formula more complicated. But, the solution we have is that we can add in our lower number and achieve what we are looking for.

Math.floor(Math.random() * (9-2) + 1) + 2

This now gives us a random number from 2-9. Replacing the numbers with upper and lower we have

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

Using this formula you can plug any numbers in and it will work. Lets try it out, something large like 60 - 78

Math.floor(Math.random() * (78 - 60) + 1) + 60

Just in case, let me go over what is happening now slowly. First Math.random() gives us a number from 0 to .99999 we then are going to multiply that by 19 because our numbers are so high and that is how the formula is working. So we come to a point where our random number will be between 0 * 19 = 0 and .99999 * 19 = 18.9981. So far not useful. But, lets apply the Math.floor() which we know gives us the closest whole number going back towards 0 so we now have a random number between 0 and 18. Now lets add back in the lowest number which is 60 and we get what we were looking for. A random number between 60 and 78.

So the formula may look intimidating but, it isn't if you allow yourself to break it down and see what it really is doing.

Best of luck with challenge!

Erik Nuber
Erik Nuber
20,629 Points
Math.floor(Math.random() * (upper - lower + 1)) + lower;

breaking this down.

Math.random will produce a random number anywhere between 0 and 1. This will include 0 and will not include 1. This also means that any fraction is also returnable... ie 0.25 0.576 etc

Because of this, additional math is needed. If we want a number between 1 and 6 we need to do some simple multiplication. However before the multiplication is done, you have to find what number to multiply to

if we use the above formula we get 6 - 1 + 1 which is 6. This means we want a number that is at it's greatest 6. we then need to subtract the lowest number we want which in this case is 1. So now we would get a number from 0 to 5. Now we have to add one back in.

Before moving on, reconsider needing a number from 10 to 15. So we start with 15 - 10 + 1 and again get 6.

In both cases we arrive at the same number, that is coincidence but, we then multiply the number returned from math.random and we arrive at some number between 0 and 1 and multiply it by 6 in both of these cases. This will still give us a fractional number and, can still include 0 which we aren't looking for.

Math.floor will take any given number and round it down to it's closest integer. That means 5.678 will be 5. and 0.453 will be 0 etc.

Because of this, we now have to add back in the lower value. This will eliminate the problem that would arise if we reached 0.

So lets go back to our first example of 1 - 6...

lets say we have a random number of .475. This would get multiplied by 6 and we would get 2.85. Math.floor would make this a 2. So far so good. We now have to add in the lower number of +1 and we would now have our returned number as being equal to 3.

Just to illustrate what would happen if the random number ended up being 0 in this case, we would multiply 0 by 6 and end up with 0 well, without adding in the lower number we would end up with that and would not meet the requirement of being between 1 and 6.

Now for the second example of a number between 10 and 15. Lets say this time our random number was 0.04 when multiplied by the 6 we again arrived at by 15-10+1 we get 0.24 which Math.floor would round it down to 0. Again, a problem because we are looking for a number between 10 and 15. So again, we have to add in the lower and we would get the number 10.

If we got a higher random number like 0.89 we would multiply that again by the 6 and end up with 5.34 which math.floor would make 5. We add in the lower number 10 and arrive at 15.

I hope that helps!

Amber Touch
Amber Touch
2,339 Points

I appreciate your effort in typing this out. I still don't really understand. I get parts of it, but not all of it. Maybe if I take several days and keep going over it again and again and again it will sink in. Or not.

rydavim
rydavim
18,813 Points

I'm going to assume the following code is the bit you're talking about, if not let me know and we can go through your code together.

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

First off, Math.floor returns the largest whole number less than or equal to the given number. Think of this as just eliminating any fractions we might run into after using Math.random.

Math.random returns a random decimal number between 0 and anything less than 1. For the following example, we'll use 0.123 - just pretend that's what the computer generated.

Because we want a whole number between our upper and lower parameters, we need to multiple that 0.123 we got above by some values to convert it into the random number we're looking for. In this case, let's pretend we're looking for a number between 15 (lower) and 35 (upper).

Given the above, our example formula would look like: 0.123 * (35 - 15 + 1) + 15, which ends up being 17.583. Because we used Math.floor that 17.583 is going to be 17.

The (upper - lower + 1) gives us the range of numbers we want to include, and then the + lower makes sure we're starting from lower instead of from zero.

Hopefully that all makes sense, but let me know if you have any more questions. Happy coding!

Amber Touch
Amber Touch
2,339 Points

I didn't even know where to start to write this challenge. When I opened workspaces there was the new code in there that I already couldn't understand :S so.... yeah.

I really do appreciate your attempt to help. Maybe someday I will get it. Right now I think my brain has blown a fuse and I'll have to try again at a later time.

Randy Singh
seal-mask
.a{fill-rule:evenodd;}techdegree
Randy Singh
Full Stack JavaScript Techdegree Student 1,462 Points

I get it to an extent, but to Ambers note above and others that have a hard time and get discouraged at this, Is this something we will run into in the industry and be obligated to know, or can we get by with about 50% understanding. (I ask b/c I see like minded people totally give up on learning to code from exercises like this, especially when they are trying to make a jump/shift in their careers)

David Kanwisher
David Kanwisher
9,751 Points

Just curious, 4 months later does this formula look more manageable to you?

Erik Nuber
Erik Nuber
20,629 Points

Been a long time since this was originally answered. I've been working as a web developer and designer for a big compnay now for almost a year and, have not needed to generate random numbers for anything. I have to say even the people I work with that have been coding for ten plus years are basically glorified google searchers. Meaning we all have to look stuff up. You get quite used to what you are doing on a daily basis but, things you don't remember are just a search away. So don't let a small set back like worrying about if you will remember this or that code ever stop you. Even completely understanding one thing or another should not deter your determination. You just press on and you will find that these types of things are either apart of your daily routine that you use frequently and easily remember or you know they exist and can quickly search for the code and move on.

Erik Nuber
Erik Nuber
20,629 Points

As far as grasping or not, the formula is what matters. It does work if you plug in numbers but, it is just a piece of code. It shouldn't give you a hick up to not just press on. They give you the formula and you can use it to generate what you need. I'm sorry I can't figure out a better way to explain.

Amber Touch
Amber Touch
2,339 Points

I take your word for it that it works! And really, it is very kind of you to explain so deeply and with so much detail. I hope that other people will also benefit from your efforts. Maybe you could append the lesson with this as a sticky or something, because god knows the video does nothing to even attempt to clarify.

I agree that this is not very well explained in the videos and far harder to grasp then the structure of javascript.

Thank you Erik i have understood how it works now and i am sure i will need to come back multiple times to remember how this works. Guys don't give up make note of the ones you don't understand and always come back to them.

Amber Touch
Amber Touch
2,339 Points

Again, many thanks for your help. I got lost when you started subtracting the lower number from the upper number. I don't understand why one would do that.

Amber Touch
Amber Touch
2,339 Points

So, I'm wondering at this point if I should just accept that this is not something I'll fully grasp and move on with studying JavaScript in hopes that it makes sense at some later time. I keep seeing the Random Number Generator and it gets harder and more complicated each time, but at this lesson it jumped like 12 levels of complexity at once lol. If it keeps doing that.... I'm not sure.

Erik Nuber
Erik Nuber
20,629 Points

You have only two numbers to work with a starting number and an ending number, or in our case higher and lower.

These two digits are ultimately what matters. If you have an odd numbered die 2-9, you can only roll a number between that.

So if we subtract two from both, you would have a number between 0 and 7 and, you already know that using 7 as the upper number we would have

Math.floor(math.Random() * 7) + 1

is going to give you a random number between 1 and 7. Our job is to take that base and figure out now how we can create a number from 2-9. So we subtract upper from lower to give us that base line. (If it was 60 and 78, we subtract and we end up with 18. So our job is to find a way to turn 1-18 into a number between 60-78. So you are ultimately subtracting the two numbers to give you a baseline of where you are starting.)

In this case, we can't just add in a one and fix it. If we added the one after this math was done, we would have a number between 1+1 = 2 and 1+7= 8 so it would be between 2-8.

So we have to add the number in before the random number is generated

Math.floor(math.Random() * 7 + 1) + 1

which again you know gives us a random number from 1 to 8. If we remove the +1 outside of the brackets, we would have

Math.floor(math.Random() * 7 + 1)

which would give us a random number between 0 and 7 because we are no longer adding in one to it. In order to get to where we need to be we need to add in 2 which just so happens to be what our lower number equals.

If you plug in any number into upper and lower, this is the formula that works

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

Just try it out for any combination of numbers you want and do the math. It works.