Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why does this random() distribution look asymmetric?

Screenshot

Edit: This is using Google Chrome 36

I was messing around with html5 canvas, generating points randomly distributed inside a cube and projecting that onto a 2D canvas. Surprisingly, the results don't look very symmetric at all, and I suspect that Javascript's Math.random() is letting me down.

Can anyone tell me why this is happening? Is it possible to make it actually look random, without making it slower?

var ctx = canvas.getContext('2d');

for (var i = 0; i < 10000000; i++) {
    var x = Math.random()*2-1, y = Math.random()*2-1, z = 2+Math.random()*2-1;
    x = (.5 + .5*x/z) * canvas.width;
    y = (.5 + .5*y/z) * canvas.height;
    ctx.fillRect(Math.floor(x), Math.floor(y), 1, 1);
}

http://jsfiddle.net/y10tvj26/ (Takes a while to load)

like image 564
doeke Avatar asked Aug 12 '14 19:08

doeke


1 Answers

Chrome has a documented issue that subsequent calls to Math.random() are correlated. In your algorithm, correlated values will tend to fall on a line on the canvas. An extra call to Math.random() breaks that correlation. I haven't seen reports that other browsers are affected.

Just call Math.random() an extra time on each call, and you'll get what you want.

var ctx = canvas.getContext('2d');

function r() {
    Math.random();
    return Math.random();
}
for (var i=0; i<10000000; i++) {
    var x = r()*2-1, y = r()*2-1, z = 2+r()*2-1;
    x = (.5 + .5*(x/z)) * canvas.width;
    y = (.5 + .5*(y/z)) * canvas.height;
    ctx.fillRect(x, y, 1, 1);
}

Updated on: http://jsfiddle.net/y10tvj26/5/

like image 51
jimm101 Avatar answered Oct 17 '22 06:10

jimm101