Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Better random function in JavaScript

I'm currently making a Conway's Game of Life reproduction in JavaScript and I've noticed that the function Math.random() is always returning a certain pattern. Here's a sample of a randomized result in a 100x100 grid:

enter image description here

Does anyone knows how to get better randomized numbers?

ApplyRandom: function() {

    var $this = Evolution;

    var total = $this.Settings.grid_x * $this.Settings.grid_y;
    var range = parseInt(total * ($this.Settings.randomPercentage / 100));

    for(var i = 0; i < total; i++) {
      $this.Infos.grid[i] = false;
    }

    for(var i = 0; i < range; i++) {
      var random = Math.floor((Math.random() * total) + 1);
      $this.Infos.grid[random] = true;
    }

    $this.PrintGrid();
  },

[UPDATE]

I've created a jsFiddle here: http://jsfiddle.net/5Xrs7/1/

[UPDATE]

It seems that Math.random() was OK after all (thanks raina77ow). Sorry folks! :(. If you are interested by the result, here's an updated version of the game: http://jsfiddle.net/sAKFQ/

(But I think there's some bugs left...)

like image 348
Danny Coulombe Avatar asked Jun 02 '13 16:06

Danny Coulombe


People also ask

Is JavaScript random good?

The JavaScript Math. random() method is an excellent built-in method for producing random numbers. When Math. random() is executed, it returns a random number that can be anywhere between 0 and 1.

Is there a random function in JavaScript?

Javascript creates pseudo-random numbers with the function Math. random() . This function takes no parameters and creates a random decimal number between 0 and 1. The returned value may be 0, but it will never be 1.

Is JavaScript math random safe?

Note: 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.


2 Answers

This line in your code...

var position = (y * 10) + x;

... is what's causing this 'non-randomness'. It really should be...

var position = (y * $this.Settings.grid_x) + x;

I suppose 10 was the original size of this grid, that's why it's here. But that's clearly wrong: you should choose your position based on the current size of the grid.


As a sidenote, no offence, but I still consider the algorithm given in @JayC answer to be superior to yours. And it's quite easy to implement, just change two loops in ApplyRandom function to a single one:

var bias = $this.Settings.randomPercentage / 100;
for (var i = 0; i < total; i++) {
  $this.Infos.grid[i] = Math.random() < bias;
}

With this change, you will no longer suffer from the side effect of reusing the same numbers in var random = Math.floor((Math.random() * total) + 1); line, which lowered the actual cell fillrate in your original code.

like image 176
raina77ow Avatar answered Oct 03 '22 00:10

raina77ow


Math.random is a pseudo random method, that's why you're getting those results. A by pass i often use is to catch the mouse cursor position in order to add some salt to the Math.random results :

Math.random=(function(rand) {
  var salt=0;
  document.addEventListener('mousemove',function(event) {
    salt=event.pageX*event.pageY;
    });
return function() { return (rand()+(1/(1+salt)))%1; };
})(Math.random);

It's not completly random, but a bit more ;)

like image 27
nfroidure Avatar answered Oct 03 '22 00:10

nfroidure