21

How is randomness achieved with Math.random in javascript? I've made something that picks between around 50 different options randomly. I'm wondering how comfortable I should be with using Math.random to get my randomness.

ЯegDwight
  • 24,821
  • 10
  • 45
  • 52
David
  • 14,569
  • 34
  • 78
  • 107
  • 3
    @David: it's not true randomness as you know. Attributed to John von Neumann: *"Anyone who considers arithmetical methods of producing random digits is, of course, in a state of sin."* They're using a PRNG. Pseudo-Random Number Generator. – cocotwo Feb 26 '10 at 19:40
  • @cocotwo: that doesnt mean all JS has to be psuedo random, from the spec Bob posted below, it CAN be real random. It would just be up to the implementation to use a real RNG, which is not as difficult as it once was. – Neil N Feb 26 '10 at 19:51
  • 2
    As some answers below say, it really depends on what you want to do. I suspect for 99% of cases, `Math.random` is fine, but it can potentially be predicted. – Alex Wayne Feb 26 '10 at 19:52

5 Answers5

17

From the specifications:

random():

Returns a Number value with positive sign, greater than or equal to 0 but less than 1, chosen randomly or pseudo randomly with approximately uniform distribution over that range, using an implementation-dependent algorithm or strategy. This function takes no arguments.

So the answer is that it depends on what JavaScript engine you're using.

I'm not sure if all browsers use the same strategy or what that strategy is unfortunately

It should be fine for your purposes. Only if you're doing a large amount of numbers would you begin to see a pattern

Chava Geldzahler
  • 3,605
  • 1
  • 18
  • 32
Bob
  • 7,851
  • 5
  • 36
  • 48
  • @cocotow et al. I was wondering weather or not that psudo-randomness is good or not? like i would guess that its porobobly not good enough for vegas or science but is it good enough for everyday needs? (i made osmething that will make decisions for me based off of a list of possible decisisons. – David Feb 26 '10 at 19:52
  • 4
    It's good enough for everyday needs, which is what Javascript's `Math.random()` is for. That's fine. – John Feminella Feb 26 '10 at 19:53
  • 1
    @JohnFeminella Please define "everyday needs" – user877329 Apr 23 '15 at 10:19
  • @Bob this is only about the seed. Not which engine it uses. – user877329 Apr 23 '15 at 10:20
  • @user877329: If you want a random number that will not be used as an entropy source (e.g. for cryptographic purposes, or where you absolutely need to guarantee randomness, like at a casino), then `Math.random()` is fine. Otherwise, don't use it. – John Feminella Apr 23 '15 at 14:46
13

Using Math.random() is fine if you're not centrally pooling & using the results, i.e. for OAuth.

For example, our site used Math.random() to generate random "nonce" strings for use with OAuth. The original JavaScript library did this by choosing a character from a predetermined list using Math.random(): i.e.

for (var i = 0; i < length; ++i) {
    var rnum = Math.floor(Math.random() * chars.length);
    result += chars.substring(rnum, rnum+1);
}

The problem is, users were getting duplicate nonce strings (even using a 10 character length - theoretically ~10^18 combinations), usually within a few seconds of each other. My guess this is due to Math.random() seeding from the timestamp, as one of the other posters mentioned.

Nick Baicoianu
  • 2,275
  • 20
  • 15
  • 3
    +1 for describing how timestamp based seeding may generate duplicate numbers in concurrent environments. – Twilite Feb 15 '13 at 13:48
3

The exact implementation can of course differ somewhat depending on the browser, but they all use some kind of pseudo random number generator. Although it's not really random, it's certainly good enough for all general purposes.

You should only be worried about the randomness if you are using it for something that needs exceptionally good randomness, like encryption or simulating a game of chance in play for money, but then you would hardly use Javascript anyway.

Guffa
  • 687,336
  • 108
  • 737
  • 1,005
2

It's 100% random enough for your purposes. It's seeded by time, so every time you run it, you'll get different results.

Paste this into your browsers address bar...

javascript:alert(Math.random() * 2 > 1);

and press [Enter] a few times... I got "true, false, false, true" - random enough :)

Timothy Khouri
  • 31,315
  • 21
  • 88
  • 128
  • 1
    Your code example doesn't show the randomness of the random generator, as you have introduced a skew. It will result in more false values than true values. A very slight difference, but still an example of how you can reduce the quality of the randomness by using it wrong. – Guffa Feb 26 '10 at 19:50
  • True... but if I had 50 check boxes... even the *sample* that I gave would be good enough for the David's question. – Timothy Khouri Feb 26 '10 at 19:53
1

This is a little overkill...but, I couldn't resist doing this :)

You can execute this in your browser address bar. It generates a random number between 0 and 4, 100000 times. And outputs the number of times each number was generated and the number of times one random number followed the other.

I executed this in Firefox 3.5.2. All the numbers seem to be about equal - indicating no bias, and no obvious pattern in the way the numbers are generated.

javascript:
var max = 5;
var transitions = new Array(max);
var frequency = new Array(max);
for (var i = 0; i < max; i++)
{
     transitions[i] = new Array(max);
}
var old = 0, curr = 0;
for (var i = 0; i < 100000; i++)
{
   curr = Math.floor(Math.random()*max);
   if (frequency[curr] === undefined) 
   {
      frequency[curr] = -1;
   }
   frequency[curr] += 1;
   if (transitions[old][curr] === undefined)
   {
      transitions[old][curr] = -1;
   }
   transitions[old][curr] += 1;
   old = curr;
}
alert(frequency);
alert(transitions);
Aishwar
  • 9,284
  • 10
  • 59
  • 80
  • 2
    This is not overkill at all - It's completely insufficient. Looking at the distribution doesn't tell you much about the entropy quality, and as others have said, the exact behavior is implementation-dependent, so testing Firefox 3.5.2 says nothing about the general situation. – Chris Martin Jun 08 '15 at 20:46