2490

How can I generate random whole numbers between two specified variables in JavaScript, e.g. x = 4 and y = 8 would output any of 4, 5, 6, 7, 8?

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
zacharyliu
  • 25,578
  • 4
  • 21
  • 15
  • 2
    here is a useful gist: https://gist.github.com/kerimdzhanov/7529623 – Dan K.K. Nov 18 '13 at 15:36
  • 15
    As a side note: for those using npm and looking for a quick, reliable and ready-made solution there's [lodash.random](https://www.npmjs.com/package/lodash.random) that can be easily required with a super small footprint (it will import just the method itself and not the whole lodash). – Aurelio Sep 08 '15 at 16:10
  • if it need to be crypto secure https://developer.mozilla.org/en-US/docs/Web/API/RandomSource/getRandomValues – happy Dec 12 '15 at 23:46
  • Can you be *[explicit](https://stackoverflow.com/posts/1527803/edit)* in the question about the number range? In particular, zero. What about negative numbers? (*"[Texts that](https://en.wikipedia.org/wiki/Natural_number) exclude zero from the natural numbers sometimes refer to the* ***natural numbers together with zero*** *as the whole numbers"*). (But ***without*** "Edit:", "Update:", or similar - the question should appear as if it was written today.) – Peter Mortensen Apr 29 '22 at 11:04
  • 2
    Many answers here answer some *different question* (they are not real answers). It is like some users only read *"Generating random whole numbers"* and never get to the ***"in a specific range"*** part (or even the body with the [4; 8] example). – Peter Mortensen Apr 29 '22 at 13:44
  • The corresponding one for Java (102 answers, incl. deleted): *[How do I generate random integers within a specific range in Java?](https://stackoverflow.com/questions/363681/)* – Peter Mortensen Oct 04 '22 at 16:16

40 Answers40

4783

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.

pgSystemTester
  • 8,979
  • 2
  • 23
  • 49
Ionuț G. Stan
  • 176,118
  • 18
  • 189
  • 202
  • 1
    Could you explain why you need to add one to the max-min? I don't understand that part. – zacharyliu Oct 06 '09 at 20:12
  • 18
    It's only doing that because it's calling `floor`, which rounds down. – Josh Stodola Oct 06 '09 at 20:17
  • 6
    @thezachperson31 You could use `round`, but then both, `min` and `max` only had half the chance to roll like the other numbers do. You could also substract one and take `ceil`. This however leaves the `max` number with a minimal less chance to roll due to the `[0,1)` Interval. – Christoph Dec 22 '12 at 09:18
  • 1
    Is anyone getting an unusual amount of Min? I have run this many times on an integer range of [0-10] and I seem to be getting 0 an awful lot. Is it just coincidence? maybe I should use round. – Leo Apr 18 '13 at 14:21
  • 19
    I've created a JSFiddle if anyone wants to test the distribution of this method: http://jsfiddle.net/F9UTG/1/ – ahren Jun 05 '13 at 13:56
  • 2
    Why add 1 to (max - min)? Because the interval from min to max includes (max - min + 1) integers. Ex: min=4,max=6 means 3 values (4,5,6), not 2, because you count both endpoints. To get 4,5, or 6 equally often from Math.floor(x), which just cuts off the fractional part, you want x to be chosen randomly from an interval that starts at 4 (min) and extends to, but not incl, 7 (max+1). That x interval has a width of (max+1)-min = max-min+1 (there's your answer!) = 3, and chopping off the fractional part of 4.2 or 5.5 or 6.7 leaves you with one of your 3 desired integers, all equally likely. – Glen Dec 24 '13 at 21:15
  • If you are getting 0 allot wait a little bit... The random function uses time into its equation to give you a random number. So that could be a factor of inconsistency. I would love to see this test on a cron job through out the day with a sum of each number chosen. My reference is here https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Math/random – Scuba Josh Jul 03 '14 at 00:00
  • 2
    This is great except for getRandomInt() I'm showing that the max is exclusive not inclusive. If I run getRandomInt(0, 10) five thousand times I never get 10 but do get 0. Am I missing something? – Evan Hobbs Jul 12 '14 at 18:19
  • 1
    @EvanHobbs how do you know the 5001st number would not have been 10? – Ionuț G. Stan Jul 12 '14 at 19:17
  • 1
    @IonuțG.Stan Well by my figuring the probability is 1.0878630073488064e-207 of not getting a 10 if it's possible. I did it several times so it's even more unlikely – Evan Hobbs Jul 13 '14 at 03:18
  • @EvanHobbs not sure what to say... it appears in my quick tests. Are you sure you're using the right function? – Ionuț G. Stan Jul 14 '14 at 10:48
  • @IonuțG.Stan ah, I see now - I thought you had copied the example directly from the mozilla developer page where the max is exclusive but it looks like you modified it slightly by adding one to make max inclusive (or they changed it after this question). thanks – Evan Hobbs Jul 15 '14 at 17:04
  • I made a little page that does it for you: http://adamzerner.github.io/randomInRange/ – Adam Zerner Nov 12 '14 at 15:43
  • `var randomIntRange = (min, max) => Math.floor(Math.random() * (max - min + 1)) + min;` One liner using ES6 arrow functions. – DifferentPseudonym Jan 26 '16 at 16:31
  • I don't understand the basic concept of this, in the basic form "random * (max - min)" with a max =10 and min = 5 will give "random * 5", surely this would return a value between 0 and 5 rather than between 5 and 10? – JackFrost Jan 26 '16 at 21:02
  • @JackFrost "Don't forget to add min back, so that we get a number in the [min, max) interval:" – Ionuț G. Stan Jan 27 '16 at 08:06
  • @IonuțG.Stan thank you so much, being so dumb, the math I gave will give a value between 0 and 5 but then you add the min so it gives between 5 and 10! – JackFrost Jan 27 '16 at 14:18
  • 10
    @JackFrost yeah, that's right. You're not dumb, you're just learning :) – Ionuț G. Stan Jan 27 '16 at 14:19
  • 4
    This question is old, but understanding this answer took me way too much time O.o, I think expanding math.random on next JavaScript version would be kind of useful – David Ortega Mar 08 '16 at 16:09
  • @SangameshDavey using [`Math.max()`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Math/max) and [`Math.min()`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Math/min) ? – Nil Jan 26 '17 at 20:10
  • 1
    The int one is faster if you use `return Math.random() * (max - min) + min | 0;` instead of `Math.floor`. `Math.floor` is a function on an object which can be replaced and so has to be checked where as `| 0` is an operator and therefore can not be replaced and no checks needed. – gman Aug 14 '17 at 08:55
  • Try generate a random number between 10^10 and 10^16 and see how it will fail. I wouldn't call random when the last 5 digits are padded with zeros. It gets worse as you go from 10^12 and up ... 10^12 is not even large. There are better ways to get true randomness and utilize the entire 2^53-1. – mjs Aug 24 '17 at 17:20
  • @momomo we're looking forward to your answer. Also, not sure where you've tested these, but they work fine for me. – Ionuț G. Stan Aug 25 '17 at 05:06
  • @IonuțG.Stan Challenge accepted. Here are three test runs. https://hastebin.com/ikefogiyoz.lisp ... see the zeros at the end? That's because Math.random() in JS (ran in Chrome inspector) cannot guarantee more than 12 decimals ( from tests performed, could not find info online on this ) – mjs Aug 25 '17 at 09:32
  • @momomo you're falling outside the range of safe numbers by using those values. I think the functions are correct given the limitations of numbers in JS: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Number/isSafeInteger – Ionuț G. Stan Aug 25 '17 at 09:40
  • Oh, yes, my bad, i had mistaken the 2 for 10^53. it suggest a maximum of 10^16, although my experience with random is that 10^12. – mjs Aug 25 '17 at 11:32
  • Consider the fact that on the borders it might be tricky for all: round, ceil and floor – Ivan Reznikov Feb 07 '18 at 09:23
  • If the question is how to generate whole numbers in a specific range, the first snippet posted should do exactly that. Now it generates floats instead. Just my 2 cents. – user130496 Jan 09 '19 at 09:35
  • For anyone having a hard time understanding this, write it on a piece of paper and plug in sample numbers and see what happens. In the getRandomInt() function, the interesting part is (max - min + 1). Take any arbitrary sequence of whole numbers from a to b. You can count the number of items in the sequence using b - a + 1. For example if you chose -12 for min and 22 for max, the number of whole numbers n where -12 <= n <= 22 is 22 - (-12) + 1 == 35. We choose a random number between 0 inclusive and 1 exclusive and multiply it by 35. – Spencer Stewart May 06 '20 at 18:37
  • Continued from above: We take the floor of the result, and this gives us a random number within the size of the whole number list we desire, but we don't want a number between 0 and 34, we want -22 of that, which is -22 and 12. – Spencer Stewart May 06 '20 at 18:39
  • That's why we add min back after everything gets resolved in Math.floor(). – Spencer Stewart May 06 '20 at 18:47
  • With Crypto-Safe random routine: function myRand(from, to) { let row = new Uint32Array(1); window.crypto.getRandomValues(row); return row[0] % (to - from + 1) + from; } – Denis Giffeler Aug 25 '20 at 04:48
  • 1
    it's incredibly bad form to have inclusive on the end of an int returning function. **random int functions are ALWAYS exclusive on the end.** (Since computers count from 0 to 9, not 1 to 10.) if you do have a inclusive-on-the-end random into function, you MUST include "inclusive" in the name of the function. this is universal in all languages, APIs, OS, etc. – Fattie Oct 26 '20 at 15:05
  • THANK YOU for adding the .floor() and .ceil() functions to the min and max values! I had omitted these, and was inadvertently passing strings to the function. It turns out "6" is not the same as 6, and it yields some maddening results! Adding floor and ceil ensure the inputs are actual numbers before performing the calculation, thus yielding the expected results. – Ryan Griggs Sep 15 '21 at 15:29
  • The first code example is wrong as it **NEVER** returns the MAX range, and the second example has unnecessary `Math.ceil` & `Math.floor` on the arguments when instead you can just *WRAP* them up in a `Math.floor`. I checked Mozilla docs and it's still not updated *"Getting random number between two value"* is **INCORRECT** ~> Why is the `MAX` excluded? - It shouldn't be! **If you are allowed to take *BETWEEN* 2 and 5 apples: then you *MUST* take at minimum(*at least*) 2 & at maximum(*no more than*) 5 apples.** – Aleksandar Nov 30 '22 at 15:52
  • Further, *no more than* does **not** mean *below*. Why would *minimum* be included but not *maximum*, then, even *minimum* has to be *excluded* if we go by the logic: *Exclude the min & max limits and keep the values **between** them*. Examples: #2: `getRandom(2,3)` **ALWAYS** returns `2` - that is a wrong logic, it isn't handling the *max-range*. A *max-range* is the **included max-*limit***. && #1: `getRandom(2,2)` returns `2` how is that for a **max-limit** that has to be excluded? And what if we excluded both **limits**:min`2` is not allowed & max`2` is not allowed? They're allowed limits! – Aleksandar Nov 30 '22 at 16:32
640
var randomnumber = Math.floor(Math.random() * (maximum - minimum + 1)) + minimum;
Darin Dimitrov
  • 1,023,142
  • 271
  • 3,287
  • 2,928
  • 33
    I know this is a VERY old answer, but using `(Math.random() * (maximum - minimum + 1) ) << 0` is faster. – Ismael Miguel Mar 01 '15 at 05:05
  • 23
    @IsmaelMiguel Using binary operators (`x << 0`, `x | 0`, `~~x`) instead of `Math.floor()` converts `x` into a two-complement with much smaller range than `Number.MAX_SAFE_INTEGER` (2³²⁻¹ vs. 2⁵³), thus you have to use it with caution! – le_m Jun 06 '16 at 01:49
  • @IsmaelMiguel Yo I just tried your method in the console and randomly got a negative value! Math.randRange = (minimum, maximum) => (Math.random() * (maximum - minimum + 1) ) << 0 Math.randRange(2,657348096152) -1407373159 – B''H Bi'ezras -- Boruch Hashem Feb 13 '19 at 11:00
  • @bluejayke Because 657348096152 (1001100100001100111111111111000010011000 in binary) has 40 bits, while bitwise arithmetics use 32 bits. If you do `657348096152|0` you get 218099864 (1100111111111111000010011000 in binary). – Ismael Miguel Feb 13 '19 at 19:49
  • 3
    This is a smart answer. Making the range internally [min, max+1) actually achieves the desired result of [min, max] being both inclusive. Thank you! :) – Mladen B. May 15 '19 at 06:18
240

Math.random()

Returns an integer random number between min (included) and max (included):

function randomInteger(min, max) {
  return Math.floor(Math.random() * (max - min + 1)) + min;
}

Or any random number between min (included) and max (not included):

function randomNumber(min, max) {
  return Math.random() * (max - min) + min;
}

Useful examples (integers):

// 0 -> 10
Math.floor(Math.random() * 11);

// 1 -> 10
Math.floor(Math.random() * 10) + 1;

// 5 -> 20
Math.floor(Math.random() * 16) + 5;

// -10 -> (-2)
Math.floor(Math.random() * 9) - 10;

** And always nice to be reminded (Mozilla):

Math.random() does not provide cryptographically secure random numbers. Do not use them for anything related to security. Use the Web Crypto API instead, and more precisely the window.crypto.getRandomValues() method.

Community
  • 1
  • 1
Lior Elrom
  • 19,660
  • 16
  • 80
  • 92
64

Use:

function getRandomizer(bottom, top) {
    return function() {
        return Math.floor( Math.random() * ( 1 + top - bottom ) ) + bottom;
    }
}

Usage:

var rollDie = getRandomizer( 1, 6 );

var results = ""
for ( var i = 0; i<1000; i++ ) {
    results += rollDie() + " ";    // Make a string filled with 1000 random numbers in the range 1-6.
}

Breakdown:

We are returning a function (borrowing from functional programming) that when called, will return a random integer between the the values bottom and top, inclusive. We say 'inclusive' because we want to include both bottom and top in the range of numbers that can be returned. This way, getRandomizer( 1, 6 ) will return either 1, 2, 3, 4, 5, or 6.

('bottom' is the lower number, and 'top' is the greater number)

Math.random() * ( 1 + top - bottom )

Math.random() returns a random double between 0 and 1, and if we multiply it by one plus the difference between top and bottom, we'll get a double somewhere between 0 and 1+b-a.

Math.floor( Math.random() * ( 1 + top - bottom ) )

Math.floor rounds the number down to the nearest integer. So we now have all the integers between 0 and top-bottom. The 1 looks confusing, but it needs to be there because we are always rounding down, so the top number will never actually be reached without it. The random decimal we generate needs to be in the range 0 to (1+top-bottom) so we can round down and get an integer in the range 0 to top-bottom:

Math.floor( Math.random() * ( 1 + top - bottom ) ) + bottom

The code in the previous example gave us an integer in the range 0 and top-bottom, so all we need to do now is add bottom to that result to get an integer in the range bottom and top inclusive. :D


NOTE: If you pass in a non-integer value or the greater number first you'll get undesirable behavior, but unless anyone requests it I am not going to delve into the argument checking code as it’s rather far from the intent of the original question.

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Gordon Gustafson
  • 40,133
  • 25
  • 115
  • 157
  • 1
    I realize this is about 2½ years later, but with the input 1 and 6 your function returns values 1,2,3,4 and 5, but never a 6, as it would if it was "inclusive". – some Feb 02 '12 at 22:45
  • 10
    @some, It could be worse, I am 2½ years + 1 day later ^^ – ajax333221 Feb 03 '12 at 19:21
  • +1, I tested your code, it appears to create a correct value. Creative structure to handle fixed scenarios that might be repeated a lot in the code. – Chris Apr 10 '12 at 19:10
  • Why do you have a function within a function for this? – Slava Jun 08 '17 at 11:27
  • 1
    @Alph.Dev To decouple the logic that uses the random number generator from the logic that decides exactly what random number distribution to use. When the code that uses the random number generator accepts it as a parameter (a 0-argument function that always returns a new random number) it can work with any sort of random number generator. – Gordon Gustafson Jun 09 '17 at 17:19
  • @Alph.Dev you can use this example to remove unnecessary code (and thus chances of bugs/errors). Instead of using `var flip1=SomeRandomFunction(0,1);var flip2=SomeRandomFunction(0,1);`, you can actually use this answer as `var coinFlip=getRandomizer(0,1); var flip1=coinFlip(); var flip2=coinFlip();` etc. – Jay Dadhania Oct 13 '19 at 19:38
  • (contd.) So you don't have to provide the `0,1` parameters every time. This helps in case where you want to use the randomizing function a lot of times but the upper and lower boundaries (range) is fixed. And, you can create multiple such fixed functions from the answer above like `var coinFlip=getRandomizer(0,1); var rollDice=getRandomizer(1,6); var rollTwoDice=getRandomizer(2,12); var getRandomCardFromDeck=getRandomizer(1,52); ` and so on. – Jay Dadhania Oct 13 '19 at 19:43
51

All these solutions are using way too much firepower. You only need to call one function: Math.random();

Math.random() * max | 0;

This returns a random integer between 0 (inclusive) and max (non-inclusive).

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Shams Ansari
  • 762
  • 5
  • 12
  • 2
    This is so clean. Thanks! – Moritz Schmidt Feb 08 '21 at 03:33
  • 2
    The OP was asking about a RANGE between 4 & 8, not 8 and 0 – avalanche1 Jan 12 '22 at 21:40
  • 4
    Then it doesn't work. `Math.random() * 10 | 5` outputs only `5 | 7 | 13` – avalanche1 Jan 14 '22 at 09:47
  • Beware: This answer is not reliable. Max: 5 & Min: 1 returns: 1, 3, 5. – Nishant Ghodke Jan 17 '22 at 09:29
  • 3
    There's nothing wrong with the answer. People clearly have no clue what the `|` bitwise-OR operator does. As it is stated, this solution holds true for numbers between lower bound `0` and non-inclusive upper bound `max`. – aefxx Jan 24 '22 at 18:38
  • Like many other answers here, this ***doesn't*** answer the question (my emphasis): *"How can I generate random whole numbers* ***between two specified variables*** *in JavaScript, e.g. x = 4 and y = 8 would output any of 4, 5, 6, 7, 8?"*. In other words, a random number in a *specified [range](https://en.wiktionary.org/wiki/range#Noun)/[closed interval](https://mathworld.wolfram.com/ClosedInterval.html)* ([4; 8] in the example). Even the title says *"in a specific range"*. Read, people. Read! – Peter Mortensen Apr 29 '22 at 12:42
  • @Moritz Schmidt: It may be clean, but it doesn't answer the question. – Peter Mortensen Apr 29 '22 at 12:52
  • I suspect others have suggested this (the edit queue for this answer is full and I can't approve edits) but `Math.random() * (max-min) | 0) + min` can constrain it to a range. For that, `min` is inclusive and `max` is exclusive, which (I think) is typical of random generator functions in most languages. For OP's specific question wording, you would add `1` to `max`. – Bryan K May 09 '22 at 19:13
43

Return a random number between 1 and 10:

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

Return a random number between 1 and 100:

Math.floor((Math.random()*100) + 1)
nbro
  • 15,395
  • 32
  • 113
  • 196
Prasobh.Kollattu
  • 1,665
  • 1
  • 22
  • 32
  • is your "between" inclusive or exclusive? i.e. is it [1,10], [1,10), (1,10], or (1,10)? – evandrix Nov 27 '15 at 02:58
  • 1
    It is partialy inclusive: [1, *) – Ivan Z Jan 06 '16 at 11:14
  • what is the need of + 1 at the end of the function? It works perfectly I guess. – Shachi Oct 10 '17 at 13:09
  • @Shachi: It is the lower bound (a badly chosen example). 4, as in the question, would be better. – Peter Mortensen Apr 29 '22 at 13:21
  • 1 is too special. This will break down for other numbers, e.g., 4 and 8 as in the question (the range will (approximately) be [4;12], not [4;8]). – Peter Mortensen Apr 29 '22 at 13:23
  • Can you [generalise](https://stackoverflow.com/posts/22711660/edit) your answer, please (even if the literal insertion of numbers is maintained)? E.g., so it works for 4 and 8 as in the question. (But ***without*** "Edit:", "Update:", or similar - the answer should appear as if it was written today.) – Peter Mortensen Apr 29 '22 at 13:25
39
function randomRange(min, max) {
  return ~~(Math.random() * (max - min + 1)) + min
}

Alternative if you are using Underscore.js you can use

_.random(min, max)
Codler
  • 10,951
  • 6
  • 52
  • 65
  • 2
    Underscore actually provides a `_.uniqueId()` function you can call for client side models. – originalhat Jun 01 '15 at 15:10
  • Using binary operators (`x << 0`, `x | 0`, `~~x`) instead of `Math.floor()` converts `x` into a two-complement with much smaller range than `Number.MAX_SAFE_INTEGER` (2³²⁻¹ vs. 2⁵³), thus you have to use it with caution! – le_m Jun 06 '16 at 01:50
33

If you need a variable between 0 and max, you can use:

Math.floor(Math.random() *  max);
Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
  • Is max inclusive or exclusive>? – Tree Aug 28 '18 at 19:17
  • 3
    @Tree using Math.floor max is exclusive. If you want max to be inclusive you could use Math.round. – Luke Apr 08 '19 at 10:19
  • 1
    Like many other answers here, this doesn't answer the question (my emphasis): *"How can I generate random whole numbers* ***between two specified variables*** *in JavaScript, e.g. x = 4 and y = 8 would output any of 4, 5, 6, 7, 8?"*. In other words, a random number in a specified *[range](https://en.wiktionary.org/wiki/range#Noun)/[closed interval](https://mathworld.wolfram.com/ClosedInterval.html)* ([4; 8] in the example). Even the title says *"in a specific range"*. This belongs in comments. – Peter Mortensen Apr 29 '22 at 13:04
  • @Tree To make `max` inclusive use `(max + 1)`. Do not use `Math.round()` as that will mess up the _random distribution_ at the ends of the range. – Dem Pilafian May 22 '23 at 00:03
22

The other answers don't account for the perfectly reasonable parameters of 0 and 1. Instead you should use the round instead of ceil or floor:

function randomNumber(minimum, maximum){
    return Math.round( Math.random() * (maximum - minimum) + minimum);
}

console.log(randomNumber(0,1));  # 0 1 1 0 1 0
console.log(randomNumber(5,6));  # 5 6 6 5 5 6
console.log(randomNumber(3,-1)); # 1 3 1 -1 -1 -1
Starkers
  • 10,273
  • 21
  • 95
  • 158
  • 1
    Your answer is true but I think your example is wrong.. `console.log(randomNumber(5,6)); # 9 6 6 5 7 7` Do 9 & 7 come between 5 & 6? ...... you should correct it or explain.. – Sachin May 29 '15 at 08:36
  • The last example could be considered an empty range. For example, invalid input parameters. With an *empty* result, an error thrown, or similar. – Peter Mortensen Apr 29 '22 at 11:09
21

Cryptographically strong

To get a cryptographically strong random integer number in the range [x,y], try:

let cs = (x,y) => x + (y - x + 1)*crypto.getRandomValues(new Uint32Array(1))[0]/2**32 | 0

console.log(cs(4, 8))
Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Kamil Kiełczewski
  • 85,173
  • 29
  • 368
  • 345
  • I'd recommend this –  Jul 04 '20 at 13:40
  • I went down a rabbit hole on this one trying to learn what cryptographically secure even meant. Ended up here: https://crypto.stackexchange.com/questions/39186/what-does-it-mean-for-a-random-number-generator-to-be-cryptographically-secure/39188#39188?newreg=6e4d42032f4f452f8257c311c81413bd – 55 Cancri Sep 08 '20 at 01:19
  • 5
    +1, this is the best one! However, I used `(x, y) => x + crypto.getRandomValues(new Uint32Array(1))[0] % (y - x + 1)` (integer modulo rather than floating point division) – user2297550 Dec 30 '20 at 15:32
  • Would it be possible to get an explanation of e.g. when cryptographic strength is important and why this answer is different from the `Math.random()` ones? – Bryan K May 09 '22 at 19:15
18

Here's what I use to generate random numbers.

function random(min,max) {
    return Math.floor((Math.random())*(max-min+1))+min;
}

Math.random() returns a number between 0 (inclusive) and 1 (exclusive). We multiply this number by the range (max-min). This results in a number between 0 (inclusive), and the range.

For example, take random(2,5). We multiply the random number 0≤x<1 by the range (5-2=3), so we now have a number, x where 0≤x<3.

In order to force the function to treat both the max and min as inclusive, we add 1 to our range calculation: Math.random()*(max-min+1). Now, we multiply the random number by the (5-2+1=4), resulting in an number, x, such that 0≤x<4. If we floor this calculation, we get an integer: 0≤x≤3, with an equal likelihood of each result (1/4).

Finally, we need to convert this into an integer between the requested values. Since we already have an integer between 0 and the (max-min), we can simply map the value into the correct range by adding the minimum value. In our example, we add 2 our integer between 0 and 3, resulting in an integer between 2 and 5.

dan-lee
  • 14,365
  • 5
  • 52
  • 77
Travis
  • 1,274
  • 1
  • 16
  • 33
18

Use this function to get random numbers in a given range:

function rnd(min, max) {
    return Math.floor(Math.random()*(max - min + 1) + min);
}
Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Aylian Craspa
  • 422
  • 5
  • 11
13

Here is the Microsoft .NET Implementation of the Random class in JavaScript—

var Random = (function () {
    function Random(Seed) {
        if (!Seed) {
            Seed = this.milliseconds();
        }
        this.SeedArray = [];
        for (var i = 0; i < 56; i++)
            this.SeedArray.push(0);
        var num = (Seed == -2147483648) ? 2147483647 : Math.abs(Seed);
        var num2 = 161803398 - num;
        this.SeedArray[55] = num2;
        var num3 = 1;
        for (var i_1 = 1; i_1 < 55; i_1++) {
            var num4 = 21 * i_1 % 55;
            this.SeedArray[num4] = num3;
            num3 = num2 - num3;
            if (num3 < 0) {
                num3 += 2147483647;
            }
            num2 = this.SeedArray[num4];
        }
        for (var j = 1; j < 5; j++) {
            for (var k = 1; k < 56; k++) {
                this.SeedArray[k] -= this.SeedArray[1 + (k + 30) % 55];
                if (this.SeedArray[k] < 0) {
                    this.SeedArray[k] += 2147483647;
                }
            }
        }
        this.inext = 0;
        this.inextp = 21;
        Seed = 1;
    }

    Random.prototype.milliseconds = function () {
        var str = new Date().valueOf().toString();
        return parseInt(str.substr(str.length - 6));
    };

    Random.prototype.InternalSample = function () {
        var num = this.inext;
        var num2 = this.inextp;
        if (++num >= 56) {
            num = 1;
        }
        if (++num2 >= 56) {
            num2 = 1;
        }
        var num3 = this.SeedArray[num] - this.SeedArray[num2];
        if (num3 == 2147483647) {
            num3--;
        }
        if (num3 < 0) {
            num3 += 2147483647;
        }
        this.SeedArray[num] = num3;
        this.inext = num;
        this.inextp = num2;
        return num3;
    };

    Random.prototype.Sample = function () {
        return this.InternalSample() * 4.6566128752457969E-10;
    };

    Random.prototype.GetSampleForLargeRange = function () {
        var num = this.InternalSample();
        var flag = this.InternalSample() % 2 == 0;
        if (flag) {
            num = -num;
        }
        var num2 = num;
        num2 += 2147483646.0;
        return num2 / 4294967293.0;
    };

    Random.prototype.Next = function (minValue, maxValue) {
        if (!minValue && !maxValue)
            return this.InternalSample();
        var num = maxValue - minValue;
        if (num <= 2147483647) {
            return parseInt((this.Sample() * num + minValue).toFixed(0));
        }
        return this.GetSampleForLargeRange() * num + minValue;
    };

    Random.prototype.NextDouble = function () {
        return this.Sample();
    };

    Random.prototype.NextBytes = function (buffer) {
        for (var i = 0; i < buffer.length; i++) {
            buffer[i] = this.InternalSample() % 256;
        }
    };
    return Random;
}());

Use:

var r = new Random();
var nextInt = r.Next(1, 100); // Returns an integer between range
var nextDbl = r.NextDouble(); // Returns a random decimal
Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Ariful Islam
  • 664
  • 8
  • 12
  • 2
    The MS DotNet Random class is under the [Ms-RSL](https://en.wikipedia.org/wiki/Shared_Source_Initiative#Microsoft_Reference_Source_License_(Ms-RSL)) license, which means it is copyrighted. So be careful when using this derivated code, since it may form ground for copyright-infringement cases. – JohannesB Jul 01 '19 at 11:22
12

I wanted to explain using an example:

Function to generate random whole numbers in JavaScript within a range of 5 to 25

General Overview:

(i) First convert it to the range - starting from 0.

(ii) Then convert it to your desired range ( which then will be very easy to complete).

So basically, if you want to generate random whole numbers from 5 to 25 then:

First step: Converting it to range - starting from 0

Subtract "lower/minimum number" from both "max" and "min". i.e

(5-5) - (25-5)

So the range will be:

0-20 ...right?

Step two

Now if you want both numbers inclusive in range - i.e "both 0 and 20", the equation will be:

Mathematical equation: Math.floor((Math.random() * 21))

General equation: Math.floor((Math.random() * (max-min +1)))

Now if we add subtracted/minimum number (i.e., 5) to the range - then automatically we can get range from 0 to 20 => 5 to 25

Step three

Now add the difference you subtracted in equation (i.e., 5) and add "Math.floor" to the whole equation:

Mathematical equation: Math.floor((Math.random() * 21) + 5)

General equation: Math.floor((Math.random() * (max-min +1)) + min)

So finally the function will be:

function randomRange(min, max) {
   return Math.floor((Math.random() * (max - min + 1)) + min);
}
Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
NewBieCoder
  • 249
  • 3
  • 6
11

After generating a random number using a computer program, it is still considered as a random number if the picked number is a part or the full one of the initial one. But if it was changed, then mathematicians do not accept it as a random number and they can call it a biased number.

But if you are developing a program for a simple task, this will not be a case to consider. But if you are developing a program to generate a random number for a valuable stuff such as lottery program, or gambling game, then your program will be rejected by the management if you are not consider about the above case.

So for those kind of people, here is my suggestion:

Generate a random number using Math.random() (say this n):

Now for [0,10) ==>  n*10 (i.e. one digit) and for[10,100) ==> n*100 (i.e., two digits) and so on. Here square bracket indicates that the boundary is inclusive and a round bracket indicates the boundary is exclusive.

Then remove the rest after the decimal point. (i.e., get the floor) - using Math.floor(). This can be done.

If you know how to read the random number table to pick a random number, you know the above process (multiplying by 1, 10, 100 and so on) does not violate the one that I was mentioned at the beginning (because it changes only the place of the decimal point).

Study the following example and develop it to your needs.

If you need a sample [0,9] then the floor of n10 is your answer and if you need [0,99] then the floor of n100 is your answer and so on.

Now let’s enter into your role:

You've asked for numbers in a specific range. (In this case you are biased among that range. By taking a number from [1,6] by roll a die, then you are biased into [1,6], but still it is a random number if and only if the die is unbiased.)

So consider your range ==> [78, 247] number of elements of the range = 247 - 78 + 1 = 170; (since both the boundaries are inclusive).

/* Method 1: */
    var i = 78, j = 247, k = 170, a = [], b = [], c, d, e, f, l = 0;
    for(; i <= j; i++){ a.push(i); }
    while(l < 170){
        c = Math.random()*100; c = Math.floor(c);
        d = Math.random()*100; d = Math.floor(d);
        b.push(a[c]); e = c + d;
        if((b.length != k) && (e < k)){  b.push(a[e]); }
        l = b.length;
    }
    console.log('Method 1:');
    console.log(b);

/* Method 2: */

    var a, b, c, d = [], l = 0;
    while(l < 170){
        a = Math.random()*100; a = Math.floor(a);
        b = Math.random()*100; b = Math.floor(b);
        c = a + b;
        if(c <= 247 || c >= 78){ d.push(c); }else{ d.push(a); }
        l = d.length;
    }
    console.log('Method 2:');
    console.log(d);

Note: In method one, first I created an array which contains numbers that you need and then randomly put them into another array.

In method two, generate numbers randomly and check those are in the range that you need. Then put it into an array. Here I generated two random numbers and used the total of them to maximize the speed of the program by minimizing the failure rate that obtaining a useful number. However, adding generated numbers will also give some biasedness. So I would recommend my first method to generate random numbers within a specific range.

In both methods, your console will show the result (press F12 in Chrome to open the console).

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Janaka R Rajapaksha
  • 3,585
  • 1
  • 25
  • 28
  • 3
    "random" doesn't necessarily mean "uniformly distributed". "biased" doesn't imply "non-random". random means drawn from a probability distribution. – syzygy Apr 15 '15 at 00:25
  • 6
    Can barely tell what this answer is trying to say. However, if you need random numbers for uses like lottery numbers and gambling. First you probably shouldn't be generating them on the client. Second, you need a cryptographically secure random number generator and the supplied algo is not sufficient. Calling random repeatedly does not make the result "more random". Author seems to be concerned about bias, but isn't providing a good algo for preventing it. In fact, the other short answers provided produce unbiased random numbers (assuming the underlying random generator is unbiased). – Jeff Walker Code Ranger Sep 01 '15 at 15:25
  • @JeffWalkerCodeRanger I think what he meant is that with the "normal" algorithm [i.e. `Math.floor(Math.random() * (6 - 1 + 1) + 1)`] the numbers 1 and 6 will necessarily be rolled fewer times than 2, 3, 4, and 5. However, the difference is basically insignificant. – oldboy May 17 '17 at 22:34
10

For a random integer with a range, try:

function random(minimum, maximum) {
  var bool = true;

  while (bool) {
    var number = (Math.floor(Math.random() * maximum + 1) + minimum);
    if (number > 20) {
      bool = true;
    } else {
      bool = false;
    }
  }

  return number;
}
nbro
  • 15,395
  • 32
  • 113
  • 196
user1764199
  • 165
  • 1
  • 2
  • 5
10
function getRandomInt(lower, upper)
{
    //to create an even sample distribution
    return Math.floor(lower + (Math.random() * (upper - lower + 1)));

    //to produce an uneven sample distribution
    //return Math.round(lower + (Math.random() * (upper - lower)));

    //to exclude the max value from the possible values
    //return Math.floor(lower + (Math.random() * (upper - lower)));
}

To test this function, and variations of this function, save the below HTML/JavaScript to a file and open with a browser. The code will produce a graph showing the distribution of one million function calls. The code will also record the edge cases, so if the the function produces a value greater than the max, or less than the min, you.will.know.about.it.

<html>
    <head>
        <script type="text/javascript">
        function getRandomInt(lower, upper)
        {
            //to create an even sample distribution
            return Math.floor(lower + (Math.random() * (upper - lower + 1)));

            //to produce an uneven sample distribution
            //return Math.round(lower + (Math.random() * (upper - lower)));

            //to exclude the max value from the possible values
            //return Math.floor(lower + (Math.random() * (upper - lower)));
        }

        var min = -5;
        var max = 5;

        var array = new Array();

        for(var i = 0; i <= (max - min) + 2; i++) {
          array.push(0);
        }

        for(var i = 0; i < 1000000; i++) {
            var random = getRandomInt(min, max);
            array[random - min + 1]++;
        }

        var maxSample = 0;
        for(var i = 0; i < max - min; i++) {
            maxSample = Math.max(maxSample, array[i]);
        }

        //create a bar graph to show the sample distribution
        var maxHeight = 500;
        for(var i = 0; i <= (max - min) + 2; i++) {
            var sampleHeight = (array[i]/maxSample) * maxHeight;

            document.write('<span style="display:inline-block;color:'+(sampleHeight == 0 ? 'black' : 'white')+';background-color:black;height:'+sampleHeight+'px">&nbsp;[' + (i + min - 1) + ']:&nbsp;'+array[i]+'</span>&nbsp;&nbsp;');
        }
        document.write('<hr/>');
        </script>
    </head>
    <body>

    </body>
</html>
Chris
  • 2,045
  • 1
  • 18
  • 21
10

Here is a function that generates a random number between min and max, both inclusive.

const randomInt = (max, min) => Math.round(Math.random() * (max - min)) + min;
epix
  • 133
  • 1
  • 9
  • How is that different from the previous answers? Does it work? – Peter Mortensen Apr 18 '22 at 14:31
  • Yes, it works with both min and max being inclusive in the range using Math.round function. – epix Apr 22 '22 at 09:48
  • I made the beginner mistake of posing more than one question. The capacity for more than one question is simply not there. Never ever do that. Always, always, always ***one question at a time***. – Peter Mortensen Apr 29 '22 at 13:39
  • I just tried it with min=0, max=5 and got a spread of (10%, 20%, 20%, 20%, 20%, 10%). So that is the penalty to try to cheat in an inclusive range when the algorithm doesn't support it. So the `Math.round` is problematic. You would have been better of to use `Math.floor` for an exclusive range but the spread would have been equal (20%, 20%, 20%, 20%, 20%). And then, if you wanted inclusivity you know to add 1 to the max and that is how it should be. – Stephen Quan Aug 15 '22 at 01:47
7

To get a random number say between 1 and 6, first do:

0.5 + (Math.random() * ((6 - 1) + 1))

This multiplies a random number by 6 and then adds 0.5 to it. Next round the number to a positive integer by doing:

Math.round(0.5 + (Math.random() * ((6 - 1) + 1))

This round the number to the nearest whole number.

Or to make it more understandable do this:

var value = 0.5 + (Math.random() * ((6 - 1) + 1))
var roll = Math.round(value);
return roll;

In general, the code for doing this using variables is:

var value = (Min - 0.5) + (Math.random() * ((Max - Min) + 1))
var roll = Math.round(value);
return roll;

The reason for taking away 0.5 from the minimum value is because using the minimum value alone would allow you to get an integer that was one more than your maximum value. By taking away 0.5 from the minimum value you are essentially preventing the maximum value from being rounded up.

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Learner.js
  • 71
  • 1
  • 4
7

Using the following code, you can generate an array of random numbers, without repeating, in a given range.

function genRandomNumber(how_many_numbers, min, max) {

    // Parameters
    //
    //   how_many_numbers: How many numbers you want to
    //                     generate. For example, it is 5.
    //
    //   min (inclusive):  Minimum/low value of a range. It
    //                     must be any positive integer, but
    //                     less than max. I.e., 4.
    //
    //   max (inclusive):  Maximum value of a range. it must
    //                     be any positive integer. I.e., 50
    //
    //   Return type: array

    var random_number = [];
    for (var i = 0; i < how_many_numbers; i++) {
        var gen_num = parseInt((Math.random() * (max-min+1)) + min);
        do {
            var is_exist = random_number.indexOf(gen_num);
            if (is_exist >= 0) {
                gen_num = parseInt((Math.random() * (max-min+1)) + min);
            }
            else {
                random_number.push(gen_num);
                is_exist = -2;
            }
        }
        while (is_exist > -1);
    }
    document.getElementById('box').innerHTML = random_number;
}
Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Yusuf
  • 703
  • 8
  • 13
6

Random whole number between lowest and highest:

function randomRange(low, high) {
  var range = (high-low);
  var random = Math.floor(Math.random()*range);
  if (random === 0) {
    random += 1;
  }
  return low + random;
}

It is not the most elegant solution, but something quick.

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
brooklynsweb
  • 817
  • 3
  • 12
  • 26
6

I found this simple method on W3Schools:

Math.floor((Math.random() * max) + min);
Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
NutCracker
  • 11,485
  • 4
  • 44
  • 68
5

Here is an example of a JavaScript function that can generate a random number of any specified length without using Math.random():

function genRandom(length)
{
  const t1 = new Date().getMilliseconds();
  var min = "1", max = "9";
  var result;
  var numLength = length;
  if (numLength != 0)
  {
     for (var i = 1; i < numLength; i++)
     {
        min = min.toString() + "0";
        max = max.toString() + "9";
     }
  }
  else
  {
     min = 0;
     max = 0;
     return;
  }

  for (var i = min; i <= max; i++)
  {
       // Empty Loop
  }

  const t2 = new Date().getMilliseconds();
  console.log(t2);
  result = ((max - min)*t1)/t2;
  console.log(result);
  return result;
}
Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Nilesh Pawar
  • 655
  • 7
  • 12
  • t1/t2 always very closer to 1. and hence your function returns same number when function is called repetitively .. http://jsbin.com/xogufacera/edit?js,console – Sunil B N Mar 02 '18 at 16:39
  • check the jsbin url.. you will see the output yourself – Sunil B N Mar 05 '18 at 09:26
  • It works great when length is between 4-10(As I have tested on my machine), because the values of constants T1 & T2 should have appropriate distance. – Nilesh Pawar Mar 05 '18 at 09:43
  • An explanation would be in order. E.g., what is the role of the time (timer/current date-time?)? What is the idea/gist? What is the purpose of the empty loop? To get some time to pass? What is some example output? From [the Help Center](https://stackoverflow.com/help/promotion): *"...always explain why the solution you're presenting is appropriate and how it works"*. Please respond by [editing (changing) your answer](https://stackoverflow.com/posts/45669240/edit), not here in comments (***without*** "Edit:", "Update:", or similar - the answer should appear as if it was written today). – Peter Mortensen Apr 29 '22 at 13:12
5

Math.random() is fast and suitable for many purposes, but it's not appropriate if you need cryptographically-secure values (it's not secure), or if you need integers from a completely uniform unbiased distribution (the multiplication approach used in others answers produces certain values slightly more often than others).

In such cases, we can use crypto.getRandomValues() to generate secure integers, and reject any generated values that we can't map uniformly into the target range. This will be slower, but it shouldn't be significant unless you're generating extremely large numbers of values.

To clarify the biased distribution concern, consider the case where we want to generate a value between 1 and 5, but we have a random number generator that produces values between 1 and 16 (a 4-bit value). We want to have the same number of generated values mapping to each output value, but 16 does not evenly divide by 5: it leaves a remainder of 1. So we need to reject 1 of the possible generated values, and only continue when we get one of the 15 lesser values that can be uniformly mapped into our target range. Our behaviour could look like this pseudocode:

Generate a 4-bit integer in the range 1-16.
If we generated  1,  6, or 11 then output 1.
If we generated  2,  7, or 12 then output 2.
If we generated  3,  8, or 13 then output 3.
If we generated  4,  9, or 14 then output 4.
If we generated  5, 10, or 15 then output 5.
If we generated 16 then reject it and try again.

The following code uses similar logic, but generates a 32-bit integer instead, because that's the largest common integer size that can be represented by JavaScript's standard number type. (This could be modified to use BigInts if you need a larger range.) Regardless of the chosen range, the fraction of generated values that are rejected will always be less than 0.5, so the expected number of rejections will always be less than 1.0 and usually close to 0.0; you don't need to worry about it looping forever.

const randomInteger = (min, max) => {
  const range = max - min;
  const maxGeneratedValue = 0xFFFFFFFF;
  const possibleResultValues = range + 1;
  const possibleGeneratedValues = maxGeneratedValue + 1;
  const remainder = possibleGeneratedValues % possibleResultValues;
  const maxUnbiased = maxGeneratedValue - remainder;

  if (!Number.isInteger(min) || !Number.isInteger(max) ||
       max > Number.MAX_SAFE_INTEGER || min < Number.MIN_SAFE_INTEGER) {
    throw new Error('Arguments must be safe integers.');
  } else if (range > maxGeneratedValue) {
    throw new Error(`Range of ${range} (from ${min} to ${max}) > ${maxGeneratedValue}.`);
  } else if (max < min) {
    throw new Error(`max (${max}) must be >= min (${min}).`);
  } else if (min === max) {
    return min;
  } 

  let generated;
  do {
    generated = crypto.getRandomValues(new Uint32Array(1))[0];
  } while (generated > maxUnbiased);

  return min + (generated % possibleResultValues);
};

console.log(randomInteger(-8, 8));          // -2
console.log(randomInteger(0, 0));           // 0
console.log(randomInteger(0, 0xFFFFFFFF));  // 944450079
console.log(randomInteger(-1, 0xFFFFFFFF));
// Error: Range of 4294967296 covering -1 to 4294967295 is > 4294967295.
console.log(new Array(12).fill().map(n => randomInteger(8, 12)));
// [11, 8, 8, 11, 10, 8, 8, 12, 12, 12, 9, 9]
Jeremy
  • 1
  • 85
  • 340
  • 366
  • Is there a difference between *crypto.getRandomValues* (used here) and *[Crypto.getRandomValues](https://developer.mozilla.org/en-US/docs/Web/API/Crypto/getRandomValues)*? – Peter Mortensen Apr 29 '22 at 12:08
4

Use:

<!DOCTYPE html>
<html>
    <head>
        <meta charset="utf-8" />
    </head>

    <body>
        <script>
            /*
                Assuming that window.crypto.getRandomValues
                is available, the real range would be from
                0 to 1,998 instead of 0 to 2,000.

                See the JavaScript documentation
                for an explanation:

                  https://developer.mozilla.org/en-US/docs/Web/API/RandomSource/getRandomValues
            */
            var array = new Uint8Array(2);
            window.crypto.getRandomValues(array);
            console.log(array[0] + array[1]);
        </script>
    </body>
</html>

Uint8Array creates an array filled with a number up to three digits which would be a maximum of 999. This code is very short.

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
happy
  • 474
  • 4
  • 17
  • (The syntax highlighting of "`Uint8Array`" is truly weird.) – Peter Mortensen Apr 29 '22 at 11:51
  • An explanation would be in order. E.g., what is the idea/gist? What is this *window.crypto* thingy? Why is it embedded in a web page? Would it work under [Node.js](https://en.wikipedia.org/wiki/Node.js)? From [the Help Center](https://stackoverflow.com/help/promotion): *"...always explain why the solution you're presenting is appropriate and how it works"*. Please respond by [editing (changing) your answer](https://stackoverflow.com/posts/34246349/edit), not here in comments (***without*** "Edit:", "Update:", or similar - the answer should appear as if it was written today). – Peter Mortensen Apr 29 '22 at 11:57
  • Like many other answers here, this doesn't answer the question. It answers some other question—(my emphasis) *"How can I generate random whole numbers* ***between two specified variables*** *in JavaScript, e.g. x = 4 and y = 8 would output any of 4, 5, 6, 7, 8?"*. In other words, a random number in a specified *[range](https://en.wiktionary.org/wiki/range#Noun)/[closed interval](https://mathworld.wolfram.com/ClosedInterval.html)* ([4; 8] in the example). Even the title says *"in a specific range"*. – Peter Mortensen Apr 29 '22 at 13:19
3

This is my take on a random number in a range, as in I wanted to get a random number within a range of base to exponent. E.g., base = 10, exponent = 2, gives a random number from 0 to 100, ideally, and so on.

If it helps using it, here it is:

// Get random number within provided base + exponent
// By Goran Biljetina --> 2012

function isEmpty(value) {
    return (typeof value === "undefined" || value === null);
}

var numSeq = new Array();

function add(num, seq) {
    var toAdd = new Object();
    toAdd.num = num;
    toAdd.seq = seq;
    numSeq[numSeq.length] = toAdd;
}

function fillNumSeq (num, seq) {
    var n;
    for(i=0; i<=seq; i++) {
        n = Math.pow(num, i);
        add(n, i);
    }
}

function getRandNum(base, exp) {
    if (isEmpty(base)) {
        console.log("Specify value for base parameter");
    }
    if (isEmpty(exp)) {
        console.log("Specify value for exponent parameter");
    }

    fillNumSeq(base, exp);

    var emax;
    var eseq;
    var nseed;
    var nspan;
    emax = (numSeq.length);
    eseq = Math.floor(Math.random()*emax) + 1;
    nseed = numSeq[eseq].num;
    nspan = Math.floor((Math.random())*(Math.random()*nseed)) + 1;
    return Math.floor(Math.random()*nspan) + 1;
}

console.log(getRandNum(10, 20), numSeq);

//Testing:
//getRandNum(-10, 20);
//console.log(getRandNum(-10, 20), numSeq);
//console.log(numSeq);
Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Goran B.
  • 542
  • 4
  • 14
2

Ionuț G. Stan wrote a great answer, but it was a bit too complex for me to grasp. So, I found an even simpler explanation of the same concepts at Math.floor( Math.random () * (max - min + 1)) + min) Explanation by Jason Anello.

Note: The only important thing you should know before reading Jason's explanation is a definition of "truncate". He uses that term when describing Math.floor(). Oxford dictionary defines "truncate" as:

Shorten (something) by cutting off the top or end.

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Dani Amsalem
  • 1,266
  • 17
  • 26
2

This I guess, is the most simplified of all the contributions.

maxNum = 8,
minNum = 4

console.log(Math.floor(Math.random() * (maxNum - minNum) + minNum))

console.log(Math.floor(Math.random() * (8 - 4) + 4))

This will log random numbers between 4 and 8 into the console, 4 and 8 inclusive.

Seb33300
  • 7,464
  • 2
  • 40
  • 57
Mr Ernest
  • 39
  • 2
  • 1
    This doesnt work for `maxNum = 2, minNum = 1`, the outcome is always 1. In fact, I think it's the same with any min & max that are just 1 number appart; the lower boundary is always the result. – devklick Dec 03 '21 at 21:25
1

A function called randUpTo that accepts a number and returns a random whole number between 0 and that number:

var randUpTo = function(num) {
    return Math.floor(Math.random() * (num - 1) + 0);
};

A function called randBetween that accepts two numbers representing a range and returns a random whole number between those two numbers:

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

A function called randFromTill that accepts two numbers representing a range and returns a random number between min (inclusive) and max (exclusive)

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

A function called randFromTo that accepts two numbers representing a range and returns a random integer between min (inclusive) and max (inclusive):

var randFromTo = function (min, max) {
    return Math.floor(Math.random() * (max - min + 1)) + min;
};
Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Prakhar Mittal
  • 6,315
  • 1
  • 14
  • 31
1

You can you this code snippet,

let randomNumber = function(first, second) {
    let number = Math.floor(Math.random()*Math.floor(second));
    while(number < first) {

        number = Math.floor(Math.random()*Math.floor(second));
    }
    return number;
}
Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Achintha Isuru
  • 2,662
  • 18
  • 24
  • 2
    There is an unnecessary duplicated line here. Just use `do - while` instead of `while` – Javi Marzán Nov 28 '19 at 12:55
  • This will be very slow if `first` is *1,000,000,000* and `second` is *1,000,000,042*. Perhaps [add](https://stackoverflow.com/posts/56066208/edit) some caveats to your answer? Perhaps even some benchmarks to demonstrate when the performance implications become significant (to quantify it)? (But ***without*** "Edit:", "Update:", or similar - the answer should appear as if it was written today.) – Peter Mortensen Apr 29 '22 at 13:00
1

My method of generating a random number between 0 and n, where n <= 10 (n excluded):

Math.floor((Math.random() * 10) % n)
Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Nitin Jadhav
  • 6,495
  • 1
  • 46
  • 48
0

I made this function which takes into account options like min, max, exclude (a list of ints to exclude), and seed (in case you want a seeded random generator).

get_random_int = function(args={})
{
    let def_args =
    {
        min: 0,
        max: 1,
        exclude: false,
        seed: Math.random
    }

    args = Object.assign(def_args, args)

    let num = Math.floor(args.seed() * (args.max - args.min + 1) + args.min)

    if(args.exclude)
    {
        let diff = args.max - args.min
        let n = num

        for(let i=0; i<diff*2; i++)
        {
            if(args.exclude.includes(n))
            {
                if(n + 1 <= args.max)
                {
                    n += 1
                }

                else
                {
                    n = args.min
                }
            }

            else
            {
                num = n
                break
            }
        }
    }

    return num
}

It can be used like:

let n = get_random_int
(
    {
        min: 0,
        max: some_list.length - 1,
        exclude: [3, 6, 5],
        seed: my_seed_function
    }
)

Or more simply:

let n = get_random_int
(
    {
        min: 0,
        max: some_list.length - 1
    }
)

Then you can do:

let item = some_list[n]

Gist: https://gist.github.com/madprops/757deb000bdec25776d5036dae58ee6e

madprops
  • 3,909
  • 5
  • 34
  • 42
0
  • random(min, max) generates a random number between min (inclusive) and max (exclusive)

  • Math.floor rounds a number down to the nearest integer

      function generateRandomInteger(min, max) { 
          return Math.floor(random(min, max)) 
      }
    

So to generate a random integer between 4 and 8 inclusive, call the above function with the following arguments:

generateRandomInteger(4, 9)
Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Normajean
  • 1,075
  • 3
  • 11
  • 28
0

For best performance, you can simply use:

var r = (Math.random() * (maximum - minimum + 1) ) << 0
Koby Douek
  • 16,156
  • 19
  • 74
  • 103
  • But it will not output in the specified range, e.g. [4;8]. The offset of 4 isn't there. Can you fix it? This doesn't answer the question (my emphasis): *"How can I generate random whole numbers* ***between two specified variables*** *in JavaScript, e.g. x = 4 and y = 8 would output any of 4, 5, 6, 7, 8?"*. In other words, a random number in a specified *[range](https://en.wiktionary.org/wiki/range#Noun)/[closed interval](https://mathworld.wolfram.com/ClosedInterval.html)* ([4; 8] in the example). Even the title says *"in a specific range"*. – Peter Mortensen Apr 29 '22 at 12:53
  • @PeterMortensen That's what I did.. 2 variables called `maximum` and `minimum` – Koby Douek Apr 29 '22 at 14:17
  • No, you didn't. "minimum" must be used (effectively) as a ***pure offset*** somewhere. Here it is only used in the scaling. – Peter Mortensen Oct 04 '22 at 16:25
0
// Example
function ourRandomRange(ourMin, ourMax) {
    return Math.floor(Math.random() * (ourMax - ourMin + 1)) + ourMin;
}

ourRandomRange(1, 9);

// Only change code below this line.
function randomRange(myMin, myMax) {
    var a = Math.floor(Math.random() * (myMax - myMin + 1)) + myMin;
    return a; // Change this line
}

// Change these values to test your function
var myRandom = randomRange(5, 15);
ChrisMM
  • 8,448
  • 13
  • 29
  • 48
samin
  • 482
  • 5
  • 9
  • Why *"Only change code below this line."*? It looks like something [freeCodeCamp](https://en.wikipedia.org/wiki/FreeCodeCamp) or similar would generate. Can you [clean](https://stackoverflow.com/posts/59908368/edit) it up? (But ***without*** "Edit:", "Update:", or similar - the answer should appear as if it was written today.) – Peter Mortensen Apr 29 '22 at 12:26
0

Using modern JavaScript + Lodash:

const generateRandomNumbers = (max, amount) => {
  const numbers = [...Array(max).keys()];
  const randomNumbers = sampleSize(numbers, amount);

  return randomNumbers.sort((a, b) => a - b);
};

Also, a TypeScript version:

const generateRandomNumbers = (max: number, amount: number) => {
  const numbers = [...Array(max).keys()];
  const randomNumbers: number[] = sampleSize(numbers, amount);

  return randomNumbers.sort((a: number, b: number) => a - b);
};
Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
pridegsu
  • 1,108
  • 1
  • 12
  • 27
0

This implementation works when both inputs are integers.

function randomRange(myMin, myMax) {
  return Math.floor(
    Math.random() * (Math.ceil(myMax) - Math.floor(myMin) + 1) + myMin
  );
}
simmer
  • 2,639
  • 1
  • 18
  • 22
Vince
  • 776
  • 11
  • 21
0

All of the existing answers generate a random number between some min and a max (or possibly between zero and a max) but I wanted the most random possible whole number.

Since Math.random() generates a 16 digit decimal number, the way to get maximally random positive integers is:

Math.floor(Math.random()*10**16)
Erik Pukinskis
  • 480
  • 5
  • 11
-3

Problems with the accepted answer

It's worth noting that the accepted answer does not properly handle cases where min is greater than max. Here's an example of that:

min = Math.ceil(2);
max = Math.floor(1);
for(var i = 0; i < 25; i++) {
  console.log(Math.floor(Math.random() * (max - min + 1)) + min);
}

In addition, it's a bit wordy and unclear to read if you're unfamiliar with this little algorithm.

Why is Randojs a better solution?

Randojs handles cases where min is greater than max automatically (and it's cryptographically secure):

for(var i = 0; i < 25; i++) console.log(rando(2, 1));
<script src="https://randojs.com/1.0.0.js"></script>

It also handles negatives, zeros, and everything else you'd expect. If you need to do floats or use other variable types, there are options for that as well, but I won't talk about them here. They're on the site so you can delve deeper there if needed. The final reason is pretty obvious. Stylistically, it's is much cleaner and easier to read.


TL;DR. Just give me the solution...

randojs.com makes this and a ton of other common randomness stuff robust, reliable, as simple/readable as this:

console.log(rando(20, 30));
<script src="https://randojs.com/1.0.0.js"></script>
Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Aaron Plocharczyk
  • 2,776
  • 2
  • 7
  • 15
  • 14
    Using a library for this kind of problem is too much. The point here is to understand / learn how to do it, not blackboxing the problem solving through a library. – nook Jun 06 '20 at 23:24
  • They are now on version 2.0.0 - Although I'm not sure whether this is an LTS version, I'm going to wait till I know for sure before I upgrade – Max Carroll Oct 22 '20 at 21:39
  • 1
    They also have an `npm` package I believe – Max Carroll Oct 22 '20 at 21:41
  • Version 2.0.0 is the standard version now. Version 1.0.0 is a rarely used version for people that prefer Math.random()-based computation over cryptographically secure results. It's safe to upgrade if that's your preference! – Aaron Plocharczyk Oct 23 '20 at 05:17
-3

Here's something I found on a webpage:

function randomInt(e,t){return Math.floor(Math.random()*(t-e+1)+e)}
Nirvana
  • 405
  • 3
  • 15