# [JS] So, I'm really curious about how Math.ceil works in conjunction with multiplying things from Math.random

So, when fooling around with the coding section of the page on the final part of the first JavaScript lesson, I typed in some code to test it out, because I was actually really curious.

1. console.log(Math.ceil(Math.random() * 1000) / 10);
2. console.log(Math.ceil(Math.random() * 100));
3. console.log(Math.ceil(Math.random() * 10) * 10);
4. console.log(Math.ceil(Math.random() * 5) * 20);

I had assumed that, by doing Math.random, multiplying by 1000 in Math.ceil, and then diving that total by ten, I’d get what could be a percentage of 100 with one float point, and I was right.

My next one, I had assumed that I could get an accurate rounded percentage to have no float point by doing Math.random times 100 in a Math.ceil, and I was also right.

Now, my third one was a bit tricky. I wanted to count by 10s, but still have a percentage. It worked somewhat as expected, but it only seemed to return 10, 20, or 30, even after refreshing the console many times by clicking “Run”. Not sure of why that occured.

My fourth and final one was one where I wanted to get an accurate percentage counting up by fives. I’d get a random number between 1 and 100 every time, but it would never end with a 5, just a 0. Again, not sure of why that occured.

I understand that the console in the course might not be perfect, but if I am going about it wrong, I’d really appreciate someone telling me the proper way to type it, as well as explaining what each part of the equation would do in that case. It would be easiest for me to understand if you limited it to Math.ceil and Math.random like I did for this description, as I’m still on the end of the first lesson, which is around 7% of the actual course.

There is only one justification for using the ceiling value in random generation expressions… The desired outcome is to fit a range from zero to some upper value with both endpoints included.

`````` Math.ceil(Math.random() * 10)
``````

The range would include all values, `[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10]`. Notice that there are eleven values in that list. We would only do this if this is in fact the desired range (interval).

In most cases, we would want only ten elements in that range, so would floor the generated value.

`````` Math.floor(Math.random() * 10)
``````

which generates a whole number between zero and nine, inclusive.

``````[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
``````

Now there are ten values instead of eleven. The side-effect of the function is something we must dictate so we don’t get false positives or unwanted values.

``````Math.floor(Math.random() * 10 + 1)
``````

The range of outputs would be,

``````[1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
``````

This is the generally preferred approach since that are no unexpected side-effects. If we want the zero and the 10, then it can be achieved with either the ceiling, or a slight modification of the above expression…

``````Math.floor(Math.random() * 11)
``````

See where the ambiguity comes in to play? What is with the `11`? Code needs to be readable, and understandable if a reader is to disseminate it accurately. The `floor` expression is unambiguous, which is why it is the preferred method. The above question never comes up because there are no mysterious numbers in the expression.

1 Like

Well, I suppose you’re right, but I didn’t understand half of it, I asked more specifically about Math.ceil due to the fact that it rounds up to the nearest whole number. Sure, adding one could possibly achieve what I want, but what if, like in the case of my first equation, I wanted to retain a decimal? That would make the equation that much harder, and if done wrong, could yield a result over 100.

This will give you a float without using division, or a ceiling…

``````Math.random() * 100
``````

but it won’t give you 100. The problem with using `ceil()` is that it will give 0 if `random()` returns `0`, which it can. We cannot assume that it will always round up.

The objective of `floor()` and `ceil()` is to get a rounded result. Convoluting an expression to force an outcome only confuses the code and makes clear dissemination difficult for readers and for debugging. There are more explicit ways of rendering floats (though in JavaScript this is difficult).

The only expression above that is clearly on par with reader reasoning is the first one, but it will only return a float if the number is not evenly divisible by 10, otherwise it will be an integer.

Part of the problem is that JavaScript has no `Float` class, only a `Number` class. Any number that ends in `.0` will be rendered as an integer.

1 Like

I understand that ceil can return zero, that was actually kinda my point. 0% is nothing and 100% is everything, which is exactly why I used ceil.

I don’t really understand the concept of convoluting an expression, as I’ve never heard of it before.

Also, I was curious about a math expression that would return a number between 0 and 100 in counts of 5s or 10s, not all this random stuff that still doesn’t really answer my question.

Sorry if that may seem rude, as I don’t intend for it to be.

I run it in a loop for 50 times, and the results are all counted by 10s, up until 100. No problem at all.

Your real problem is in Q4:

Dissecting your code into simple pieces, the possible numbers generated after `Math.ceil` are 0, 1, 2, 3, 4, 5. So if you calculate, neither all those numbers will give you a number ending with 5 after you multiply it with 20. Then you know, you need to tweak the formula just a little to achieve what you intended, it’s a math problem rather than coding problem.

@mtf proposed `Math.floor` is very reasonable. If you tinker with your project long enough, you will notice you hardly ever get 0 as a result in `console.log`. This is because how `Math.ceil` works, it return the smallest integer greater than or equal to a given number.

For you to get 0 as the result, unless your `Math.random` return a 0, then your `Math.ceil` will return a 0 as well. If your `Math.random` return any number above 0 like 0.000001, you will not get a 0 through `Math.ceil` because `Math.ceil(0.000001)` equals to `1`. So the chances of getting 0 is minuscule.

You can put your console.log into a loop for 1000 times. Still, barely get a `0`. Different goes for `Math.floor` because `Math.floor` returns the largest integer less than or equal to a given number.

So if ever you get a `Math.random` that generate anything from `0` to numbers like `0.989`, your `Math.floor` will be able to produce a `0`. That way, mathematically speaking and probability speaking, the chances are much fair and more distributed.

Just my two cents. Happy Coding! 1 Like