Basic JavaScript - Generate Random Whole Numbers with JavaScript
Generating random whole numbers in JavaScript in a specific range - Stack Overflow
math - JavaScript Random Number - Stack Overflow
Generating random numbers within a range.
Videos
There are some examples on the Mozilla Developer Network page:
/**
* Returns a random number between min (inclusive) and max (exclusive)
*/
function getRandomArbitrary(min, max) {
return Math.random() * (max - min) + min;
}
/**
* Returns a random integer between min (inclusive) and max (inclusive).
* The value is no lower than min (or the next integer greater than min
* if min isn't an integer) and no greater than max (or the next integer
* lower than max if max isn't an integer).
* Using Math.round() will give you a non-uniform distribution!
*/
function getRandomInt(min, max) {
min = Math.ceil(min);
max = Math.floor(max);
return Math.floor(Math.random() * (max - min + 1)) + min;
}
Here's the logic behind it. It's a simple rule of three:
Math.random() returns a Number between 0 (inclusive) and 1 (exclusive). So we have an interval like this:
[0 .................................... 1)
Now, we'd like a number between min (inclusive) and max (exclusive):
[0 .................................... 1)
[min .................................. max)
We can use the Math.random to get the correspondent in the [min, max) interval. But, first we should factor a little bit the problem by subtracting min from the second interval:
[0 .................................... 1)
[min - min ............................ max - min)
This gives:
[0 .................................... 1)
[0 .................................... max - min)
We may now apply Math.random and then calculate the correspondent. Let's choose a random number:
Math.random()
|
[0 .................................... 1)
[0 .................................... max - min)
|
x (what we need)
So, in order to find x, we would do:
x = Math.random() * (max - min);
Don't forget to add min back, so that we get a number in the [min, max) interval:
x = Math.random() * (max - min) + min;
That was the first function from MDN. The second one, returns an integer between min and max, both inclusive.
Now for getting integers, you could use round, ceil or floor.
You could use Math.round(Math.random() * (max - min)) + min, this however gives a non-even distribution. Both, min and max only have approximately half the chance to roll:
min...min+0.5...min+1...min+1.5 ... max-0.5....max
βββββ¬ββββββββββββββ¬ββββββββββββββ ... βββββββββββ¬βββ β Math.round()
min min+1 max
With max excluded from the interval, it has an even less chance to roll than min.
With Math.floor(Math.random() * (max - min +1)) + min you have a perfectly even distribution.
min... min+1... ... max-1... max.... (max+1 is excluded from interval)
βββββ¬βββββββββ¬ββββββββ ... ββββββ¬βββββββββ¬ββββ β Math.floor()
min min+1 max-1 max
You can't use ceil() and -1 in that equation because max now had a slightly less chance to roll, but you can roll the (unwanted) min-1 result too.
var randomnumber = Math.floor(Math.random() * (maximum - minimum + 1)) + minimum;
Assuming you already understand the behaviour of Math.floor and Math.random, here's the rest step by step:
Math.random()β a random number between0(inclusive) and1(exclusive)Math.random() * maxβ a random number between0(inclusive) andmax(exclusive)Math.floor(Math.random() * max)β a random integer between0(incl.) andmax(excl.)Math.floor(Math.random() * (max - min)) + minβ a random integer betweenmin(incl.) andmax(excl.)Math.floor(Math.random() * ((max + 1) - min)) + minβ a random integer betweenmin(incl.) andmax+1(excl.) (OR betweenminandmaxboth inclusive)
Math.random() will give you a "real" number from 0 to 1 (not including 1.0).
That's cool and all, but what if I want a "real" number from 1 to 2?
The answer: "transform" your [0,1) into [1,2).
In practical terms, it means adding 1 to your result.
Try it out -- Math.random()+1 will give you a number from 1 to 2.
In mathematics this is known as a "mapping". That is -- for every possible real number in [0,1), find a way to "map" that real number to another real number in [1,2). That is, if I give you any real number between [0,1), you should be able to map that number -- apply that number to a function that will return a number between [1,2).
In our case, that function f(x) = x+1.
Do you see how this gives us random numbers between [1,2)? Visualize the two intervals next to each other and imagine a line going from every point in [0,1) to its corresponding map in [1,2). Now, pick a random point on [0,1) ... and follow the line. You'll follow the line to a random point in [1,2)!
Now, all complete one-to-one maps from [0,1) to [1,2) will turn a random number between [0,1) to a random number between [1,2)...but not all of them will give you an evenly distributed random number between [1,2). The mathematics behind what maps give you evenly distributed results is a bit complicated but in short, if your map only involves adding, subtracting, multiplying, and dividing by constants, it's "legal" in the sense that the results will also be evenly distributed.
So, now we know how to transform [0,1) into [1,2).
What if I want to map [0,1) onto [0,2)? I can't just add numbers anymore ...
How about I multiply everything by two?
This should work -- the function f(x) = x*2 does indeed map every point on [0,1) to a point on [0,2) --- and because it only involves multiplication by constants (2), it is a distribution-preserving map.
This works! Math.random()*2 will give you a random number between 0 and 2.
Okay, now something a bit more complicated ... transforming [0,1) into [1,3).
Multiplying by two doesn't work ... 0*2 = 0, and that's not in your target range. Adding one doesn't work... even though 0+1 is in your target range and 1+1 is, as well, there is no way you can ever reach 3.
If we can't transform [0,1) into [1,3), let's try and see if we can transform something else into [1,3).
How about [0,2)? Yes, we can do this ... the function f(x) = x+1 perfectly maps [0,2) to [1,3). You can think of + as "shifting" the range up.
And so the solution here is clear -- first, turn [0,1) into [0,2), then turn [0,2) into [1,3).
We already know the first (f(x) = x*2), and we figured out the second (f(x) = x+1). So the "combined" transformation/map is f(x) = (x*2)+1.
That is, Math.random()*2 + 1 will give you a number from 0 to 3.
Now for the final trick...mapping [0,1) to an arbitrary range [min,max).
The secret here is to re-write this as [min,min+range), where range = max-min.
Here you can see that it's simple to transform the range [0,range) to [min,min+range) -- you just add "min" to it. So if I had the range [0,range), and I wanted to get [min,min+range), i would use f(x) = x+min.
So how do we get from [0,1) to [0,range) ?
Multiply by range!
f(x) = (x*range) + min
Now writing things back to original terms, using range = max-min
f(x) = (x*(max-min)) + min
will transform a real number from [0,1) to a real number from [min,max)
I'll leave the rest (turning it into a useful integer) to you
I'm a complete newbie not just to JavaScript but to programming altogether. And I mean, a newbie, no previous experience, just about finishing the codecademy's JS track right now and reading a couple of books atm. Codecademy's great fun but I get the feeling that being hold by a virtual hand while writing itsy bits of code is not how this is going to work, so I've decided to fiddle away at my own, obviously incredibly basic, little projects.
And for one of them I need a dice roll function which I'll be able to use for multiple types of dice (you know d4, d6, d8 etc). I came up with this:
function diceRoll(min, max) {
return Math.floor(Math.random()* (max-min)) + min;
}It's working, but can anyone tell me if it's the best option? What other ways are there to generate random numbers within a range?
it should be or instead of and
function generateRandom(min, max) {
var num = Math.floor(Math.random() * (max - min + 1)) + min;
return (num === 8 || num === 15) ? generateRandom(min, max) : num;
}
var test = generateRandom(1, 20)
One way, which will maintain the generator's statistical properties, is to generate a number in [1, 18]. Then apply, in this order:
If the number is 8 or more, add 1.
If the number is 15 or more, add 1.
I'd be reluctant to reject and re-sample as that can cause correlation plains to appear in linear congruential generators.
I was reading a thread on a post in one of the JS subs that was saying Math.random() isn't particularly good when it comes to making random numbers. Is it particularly bad? Are some use cases worse than others for using Math.random()? What are some ways to do it better?