The numbers from Math.random() are in the range 0 (inclusive) to 1 (exclusive). That means you might get a 0, but you'll never get 1.
Thus that formula starts off with multiplying by an integer, which in your example will give a value from 0 (inclusive) up to 4 (exclusive). If you want random integers like 0, 1, 2, and 3, you have to use .floor() to get rid of any fractional part entirely. In other words, you might get 3.999, and you don't want a 4, so .floor() throws away the .999 and you're left with 3.
Now this presumes that what you want is what most people want, a random integer between a minimum value and a maximum value. Once you understand what Math.random() returns, you're free to generate integers however you want.
Videos
Math.floor returns a whole number, while Math.random() will return a float between 0 and 1.
To access an item in an array, like rand[0], you need to have a whole number. You cannot access an item in array with rand[1.43].
That little line of code is going to access a random item in an array by generating a random float from zero to the array's length, and rounding it to its nearest whole number with Math.floor
Because there are no fractional array elements
const array = [123, 456];
console.log(array[0.5]);
The code above prints undefined because there is no 0.5 element. There is a 0 element and a 1 element but no 0.5 element
So, to choose a random element with Math.random() which returns a number between 0 and 1 (but not 1) you have to convert to an integer.
JavaScript arrays are not like arrays in most other languages. They're actually more like augmented objects. They act like arrays in that you can get the length (array.length) and call things like push,pop,concat,shift,unshift but you can also add properties
array = [4, 5, 6];
array["foo"] = "bar"
console.log(Object.keys(array));
Prints
[
"0",
"1",
"2",
"foo"
]
Which explains why the Math.random without the Math.floor would fail. From the semantic point of view of JavaScript an array is just an object with properties named 0, 1, 2, 3 etc. Of course under the hood that's not what JavaScript does as it would be too slow to implement arrays that way but for the most part arrays act like they are actually just an object with properties named '0', '1', '2' and it's perfectly valid to have properties named '0.00012' etc.
Note, it would actually be faster to do this
const rand = array[Math.random() * array.length | 0];
The | 0 is a binary or of 0 which the JavaScript spec effectively says the result is converted to an integer before the | happens. Note that | 0 is not the same as Math.floor. | 0 rounds toward 0 whereas Math.floor rounds down.
| 0 Math.floor
------+------+------------
2.5 | 2 | 2
1.5 | 1 | 1
0.5 | 0 | 0
-0.5 | 0 | -1
-1.5 | =1 | -2
-2.5 | -2 | -3
as stated in MDN reference about Math.random()
Returns a floating-point, pseudo-random number in the range [0, 1) that is, from 0 (inclusive) up to but not including 1 (exclusive), which you can then scale to your desired range.
Since Math.random can return 0, then Math.ceil(Math.random()*10) could also return 0 and that value is out of your [1..10] range.
About your second question, see Most efficient way to create a zero filled JavaScript array?
Math.floor() is preferred here because of the range of Math.random().
For instance, Math.random() * 10 gives a range of [0, 10). Using Math.floor() you will never get to the value of 10, whereas Math.ceil() may give 0.
You can take the floating point number (between 0 and 1, non-inclusive) and convert it to an index to the array (integer between 0 and length of the array - 1). For example:
Copyvar a = ['a', 'b', 'c', 'd', 'e', 'f'];
var randomValue = a[Math.floor(a.length * Math.random())];
Yes, this is indeed possible. Here's some example code:
Copy<script>
var arr = new Array('a', 'b', 'c', 'd', 'e');
document.write("Test " + arr[Math.floor(Math.random() * ((arr.length - 1) - 0 + 1))]);
</script>
Note that Math.floor should be used instead of Math.round, in order to get a uniform number distribution.
why don't we use Math.ceil() instead of using the floor() function then adding 1, wouldn't it be much easier?
Math.random returns a floating-point number between 0 and 1.
Returns a floating-point, pseudo-random number in the range [0, 1) that is, from 0 (inclusive) up to but not including 1 (exclusive), which you can then scale to your desired range.
Multiplying this by n gives a floating point number between 0 (inclusive) and n (exclusive).
Math.floor is then used to convert this floating point number to an integer between 0 and n - 1 (inclusive).
Why would anybody call Math.floor on a Math.random result?
In a nutshell, one calls Math.floor() when you want to truncate a decimal value to its nearest integer (by just dropping the decimal portion. So, 3.9 becomes 3, 2.1 becomes 2, etc... So, you would typically use that when you need an integer and you want the integer that is smaller than or equal to the decimal value. The math library also has Math.ceil() and Math.round(). Math.ceil() gets you the next larger integer, Math.round() rounds to the nearest integer going either up or down depending upon which is closer.
I've seen it used like:
Math.floor(Math.random() * num);
Breaking Math.floor(Math.Random() * num) down into it's individual pieces and explaining each piece, you get this:
Math.random() gives you a random decimal number between 0 and 1, including 0, but not including 1. So, it might give you something like 0.38548569372.
Math.random() * num gives you a random decimal number between 0 and num, including 0, but not including num. So, if num was 10, it might give you 3.8548569372.
Math.floor(Math.random() * num)) gives you a random integer number between 0 and num, including 0, but not including num. So, it might give you 3.
Math.floor() truncates the decimal number to only the integer portion. A random integer is often used for getting a random value from an array (which needs to be an integer).
Math.random will give you a floating point number between 0 (inclusive) and 1 (exclusive).
Multiplying that by 256 will give you a number in the range 0 (inclusive) through 256 (exclusive), but still floating point.
Taking the floor of that number will give you an integer between 0 and 255 (both inclusive).
It's the integer from 0 to 255 that you need to construct RGB values like rgb(72,25,183).
It seems a random color is desired - one with each component random between 0 and 255.
Math.random() returns a random number on [0,1) (ie it may be exactly zero or up to but not including one).
Multiplying that random value by 256 gives a random number on the range [0,256) (ie it may be 255.99, but never 256). Almost there, but not quite.
Math.floor() rounds the number downwards to the nearest whole integer, making the result an integer on [0,255] as desired.