# Why do we get random numbers that way in JavaScript?

May 10, 2023

You've definitely googled `js random number`. I know I have. This here is an explainer for me, myself, when I forget what each part of the equation does.

## Getting a random number

`Math.random()` returns a number that looks like this: `0.7212660732474856`. It's a decimal, it's long, and it's always between 0 and 1. It's inclusive of 0 but not of 1., which means that the number returned by `Math.random()` is between 0 and .9999999999999999.

If I want an integer, I take the returned number and multiply it by 10 or 100 or 322 - whatever I want the upper limit of my range to be. Say I want a number between 0 and 128.

``  Math.random() * 128``

The largest number possible is `.9999999999999999 * 128`. So, `127.99999999999999`. The smallest possible will be `0 * 128`. So, `0`.

## Cleaning up the number, two ways

The return from `Math.random()` looks all gnarly: `0.7212660732474856`. That number times the top of my range isn't gonna look great. It's gonna be `92.32205737567816`, for example. So I'm gonna wanna clean it up. Two ways to do that:

### `Math.ceil()`

This function rounds a number up to the next largest integer. When using `Math.ceil()`, both 9.001 and 9.9 round up to 10.

`Math.round()` rounds the way I was taught in school (i.e. 2.5 rounds up tp 3 and 2.3 rounds down to 2).

So, calling `Math.ceil()` with an argument of anything larger than zero returns 1. Calling it with an argument of any non-decimal (e.g. 3, 37288, 81239817381273980000) returns that integer (albeit in exponential notation if it's larger than 20 digits).

`Math.ceil(Math.random())` will almost always be 1 except on the very, very rare occasion that `Math.random()` returns exactly 0. What is `Math.ceil()` if `Math.random()` returns `.00028311`? `.28883999`? `.998778668`?

If I want a number between 0 and 128, `Math.ceil(Math.random() * 128)` will give me that. If I want a number between 1 and 128, I can tack a 1 on to the `Math.ceil()`, and take 1 off the top of the range: `Math.ceil(Math.random() * 127) + 1`

``````  Math.ceil(Math.random() * 127) + 1
// say Math.random returns .00028311
Math.ceil(.00028311 * 127) + 1
// .00028311 * 127 = 0.035954969999999996
Math.ceil(0.035954969999999996) + 1
// the argument is larger than 0, so Math.ceil()is 1
1+1 ``````
``````Math.ceil(Math.random() * 127) + 1
// say Math.random returns .28883999
Math.ceil(.28883999 * 127) + 1
// .28883999 * 127 = 36.68267873
Math.ceil(36.68267873) + 1
// the closest integer, rounding up, from 36.68267873 is 37
37+1 ``````
``````Math.ceil(Math.random() * 127) + 1
// say Math.random returns .998778668
Math.ceil(.998778668 * 127) + 1
// .998778668 * 127 = 126.844890836
Math.ceil(126.844890836 ) + 1
// the closest integer, rounding up, from 126.844890836 is 127
127+1 ``````

### `Math.floor()`

This function returns the largest integer less than or equal to a given number.

Say I want a number between 0 and 128 again. So, `Math.random() * 128`. Great. I get a number like `47.56094752691706` which I can then clean up using `Math.floor()`.

``````  Math.ceil(Math.random() * 128)
// say Math.random returns .00028311
Math.floor(.00028311 * 128)
// .00028311 * 127 = 0.035954969999999996
Math.floor(.03623808)
// rounding toward zero, Math.floor(.03623808) is 0 ``````

To get a number between 1 and 128, I've got to add a 1, just like when working with `Math.ceil()`.

``````  Math.ceil(Math.random() * 128) + 1
// say Math.random() returns .28883999
Math.floor(.00028311 * 128) + 1
// .00028311 * 128 = 36.97151872
Math.floor(36.97151872) + 1
// the largest integer less than 36.97151872 is 36
36 + 1``````
``````  Math.floor(Math.random() * 128) + 1
// say Math.random() returns .998778668
Math.floor(.998778668 * 128) + 1
// .998778668 * 128 = 127.843669504
Math.floor(127.843669504) + 1
// the largest integer less than 127.843669504 is 127
127 + 1``````

## TL;DR

For a number between 0 and 128, inclusive: `Math.ceil(Math.random() * 128)` `Math.floor(Math.random() * 129)`

For a number between 1 and 128, inclusive: `Math.ceil(Math.random() * 127) + 1` `Math.floor(Math.random() * 128) + 1`

The 1 is outside the `Math.` method to account for the rare occasions that `Math.random()` returns exactly 0.

Written by Zoe Daniels