# Unique Random Numbers

When you want just one random number in JavaScript a simple call to Math.random() will give you a single random value that can easily be converted to be an integer within the desired range.

``var getRandomInt = function (min, max) {return Math.floor(Math.random() * (max - min)) + min;}``

If you need more than one random number then you need to decide whether each number is completely independent or whether each needs to be an unique value not previously returned. If you don't care if the same number is returned multiple times then you can simply call the function multiple times and you will get a series of random numbers all within the specified range but with each being completely random such that two or more of the values returned can in fact be the same value.

If you need the returned values to be unique (that is that the values already returned are excluded from the possible values that you want subsequent calls to return) then there are two alternative approaches you can take depending on just how many of the numbers in the range you intend to retrieve.

Where the number of unique values you want to retrieve is small relative to the number of values in the range then the obvious solution is to simply test if the random value retrieved this time has been retrieved before. If it hasn't then you add it to the results. If it has already been retrieved then you simply discard it and retrieve another value.

``var getRandomInts = function(num,min,max) {var ints = [];while (ints.length < num-1) {var randNum = getRandomInt(min,max);if(!ints.indexOf(randNum) > -1){ints.push(randNum);}}return ints;} var arr = getRandomInts(5,1,91);console.log(arr);``

The problem with this approach is that as the percentage of the range of the random numbers you want to retrieve grows, the loop to get the unique random numbers will spend more and more time discarding duplicates of values already retrieved. If you have a range of 50 values and you want to retrieve 40 unique random numbers from that range then by the time you get to the 40th value to be retrieved there are 39 random values that would be duplicates and only 11 values that would be unique. If you want 45 of the 50 values then getting the 45th value has 44 values to discard and only 6 possible unique values. If you want all 50 then for the last value there are 49 values to discard and only 1 that would be unique. Each time you increase the number of entries to retrieve you end up needing to loop more times to find the next value.

There is an alternative approach where the efficiency of retrieving values doesn't degrade as the number of values to be retrieved increases. This alternative approach takes the same time to run whether you want 2 or 50 values from a range of 50 consecutive integers. What we do is to simply create an array of all of the numbers in the desired range and then simply shuffle them into a random order and then retrieve as many entries as we want off of the front of the resultant array.

``````Array.prototype.shuffle = function() {var r=[],c = this.slice(0);while (c.length) r.push(c.splice(Math.random() * c.length, 1));return r;};
Array.prototype.populate = function(n) {return Object.keys(Object(0+Array(n)));};var getRandomInts = function(num, min, max) {var a = [].populate(max).slice(min);a = a.shuffle();return a.slice(0,num);} var arr = getRandomInts(80,1,91);console.log(arr);``````

This alternative approach of generating a list of all of the numbers in the range in a random order will be less efficient than the first approach where the number of unique random values required is small and the range of vales to select from is large because the likelihood of duplicates during the random number retrieval will be small. If you want five unique random numbers out of 50 then the first approach will seldom require more than six or seven times around the loop in order to get the five unique random numbers.

Which approach you use therefore depends on how many numbers there are in the range and what percentage of them you expect to need to retrieve. If the percentage of numbers to be retrieved is very small then the first approach is best. If the percentage is very large then the second approach is best. Where it will be difficult to decide is where the percentage is somewhere in the middle or where the percentage is unknown. In these cases using the second approach will probably be the better solution as then the runtime is not dependent on the number of unique random numbers to be retrieved and the first approach can become extremely slow if a significant percentage of a large range need to be retrieved.