18

Normally this is how you get a random number in javascript.

Math.random();

However, this method seems to be inefficient when it comes to generating random integers.

Firstly, the random function has to generate a random decimal, like 0.1036098338663578, then it has to be multiplied to a suitable range (10.464593220502138). Finally, the floor function subtracts the decimals to produce the result (which in this case, 10).

var random_integer = Math.floor(Math.random()*101);

Is there a faster way to generate random integers in javascript?

Edit1:

I am using this for creating a canvas HTML5 game. The FPS is about 50, and my code is pretty optimized, apart from generating a random number.

Penny Liu
  • 15,447
  • 5
  • 79
  • 98
auroranil
  • 2,621
  • 6
  • 24
  • 34
  • 6
    "However this method seems inefficient " - have you measured it? – Mitch Wheat Jan 08 '12 at 07:12
  • 7
    How fast do you need it to be? With the code above I can get 10M random numbers in 500ms on my old laptop. – earldouglas Jan 08 '12 at 07:17
  • 1
    In most languages, you'd want a random number generator by seeding and mod'ing against some prime. In JavaScript, however, there is more overhead in the evaluation of the language than in the overhead of calls to something like Math.random() meaning that native calls are almost always faster than anything you can implement. –  Jan 08 '12 at 07:38
  • Try saving the canvas width in a var rather than accessing it everytime. It may be that simple. – King Friday Jan 08 '12 at 07:48

8 Answers8

30

This code is faster... to type.

var random_integer = Math.random()*101|0;

It won't work right for huge numbers though.

(and it doesn't run any faster, at least not in chrome.)

You could achieve a much faster speed during the game if you generate the random numbers beforehand, though.

for (var i=1e6, lookupTable=[]; i--;) {
  lookupTable.push(Math.random()*101|0);
}
function lookup() {
  return ++i >= lookupTable.length ? lookupTable[i=0] : lookupTable[i];
}

lookup will rotate through an array with a million random integers. It is much faster than calling random and floor (of course, there is a "loading time" penalty up front from generating the lookup table).

Dagg Nabbit
  • 75,346
  • 19
  • 113
  • 141
  • 1
    It runs significantly faster in almost everything but chrome –  Jan 08 '12 at 07:39
  • hmm, interesting. I usually do this because I'm lazy and it's easier to read. – Dagg Nabbit Jan 08 '12 at 07:46
  • 1
    @cwolves I just ran it in firefox with the same results... http://jsperf.com/floor-or-or – Dagg Nabbit Jan 08 '12 at 07:52
  • @user824294 add it to the jsperf and see :) – Dagg Nabbit Feb 22 '12 at 05:25
  • 2
    @Rasu Don't pre allocate the array. you can achieve 1000x faster for a very large array :) – Ghominejad Feb 03 '15 at 22:15
  • @Ghominejad the problem with Rasu's edit is it's still pushing things onto the array even though it was pre-allocated. I wonder how pre-allocating it would help performance if the assignments were done properly in the loop? Rolling back Rasu's edit for now. – Dagg Nabbit Feb 04 '15 at 17:37
  • Arrays have an "implementation determined size" in which they become less efficient - not to mention the cost of creating the array vs generating values directly. I would *not* pregenerate (or even recommend the generation of) such a [large] array, unless such shows a relevant performance improvement *in the actual usage* or is required for other purposes. – user2864740 Feb 04 '15 at 17:42
  • 3
    @DaggNabbit In node js it took more than 50 seconds then i had to stop it! because node have to change the default type of the array elements at runtime for million items. but generating 1 million items without pre-allocation took about 100ms! because it pre-allocates itself by type of the first value. you can achieve even more performance by pre-allocating [Typed arrays](https://developer.mozilla.org/en/docs/Web/JavaScript/Typed_arrays) in javascript. – Ghominejad Feb 05 '15 at 14:05
  • @user2864740 I agree that in general this should not be necessary, but the OP claims that the RNG is a bottleneck in this case, and pre-generating the random numbers does seem to help significantly in most versions of most browsers. I assume using a seeded PRNG (which most games would probably want to do) would be significantly slower than Math.random, but the lookup time would of course be the same. Do you know of a better way to address this? – Dagg Nabbit Feb 05 '15 at 18:34
  • I'd first make sure that "this method seems to be inefficient" is accurate / relevant. A simple [LCG](http://www.researchgate.net/profile/Karl_Entacher/publication/228386019_Bad_subsequences_of_well-known_linear_congruential_pseudorandom_number_generators/links/00b4952247ee06caab000000.pdf) PRNG implementations takes "inconsequential time" - assuming it is called only as relevant - compared to everything else that has to occur in a game that does .. game stuff. If these PRNGs are only every used once then the array can "move the work" but won't reduce the overall cycles consumed. – user2864740 Feb 05 '15 at 18:49
  • Thats a lot of wasted storage space though. – Trevor Blythe Dec 30 '21 at 16:19
4

If you want to avoid floating point calculation then you can do that by writing your own pseudo random number generator. Here is a list of well known pseudo random number generators (PRNG). Linear congruential generator is the easiest one to implement and probably most effective in terms of performance too. However, you will need to understand the theory behind PRNGs well enough to write an effective one. That might not be worth of effort though. The JS implementation should be effective enough. At the end there is a high possibility that you will find Math.random() is running faster than your code.

taskinoor
  • 45,586
  • 12
  • 116
  • 142
2

Heres what I use:

function getRandomInt(max) {
    return Math.floor(Math.random() * max);
}

An example of how this would be used would be

function getRandomInt(max) {
return Math.floor(Math.random() * max);
}
if(getRandomInt(420) == 69){
console.log("nice")
}
Mimic
  • 21
  • 3
1

i mostly use

    var a = Math.floor(Math.random((number you'd like to be minimum, (number you'd like to be maximum) * (number you'd like to be maximum);
Qyther
  • 31
  • 4
0
const getRandomInt = (base = 10) => {
  return Math.floor(Math.random() * base)
}
Marc Lundgren
  • 59
  • 1
  • 4
  • This is a more 2017-appropriate method than the previous answers – Marc Lundgren Jun 09 '17 at 19:50
  • This is a more "let's just ignore that Dagg Nabbit has already posted almost the exact same answer" method than the previous answers. Although your code "works", it is a near duplication of Dagg Nabbit's answer. In such a case as this, I would recommend making an edit suggested to his answer instead of posting it as your own answer. – Jack G Oct 18 '18 at 20:36
0

No, there is no easier or shorter way. You can create a function if you need to do it multiple times, though.

blake305
  • 2,196
  • 3
  • 23
  • 52
-1

This is the shortest one-liner Random Number Generator code

rnd=(a,b)=>~~(Math.random()*(b-a))+a

How To Use: rnd(min,max) Example : rnd(10,100)

ABJ4403
  • 13
  • 3
-1

Your way is the right way to retrive a random integer in javascript, don't worry about performance it will run fast.

brentonstrine
  • 21,694
  • 25
  • 74
  • 120
aleroot
  • 71,077
  • 30
  • 176
  • 213