Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why are my particles drifting? ( aka Is Math.random() broken or is it my algorithm? )

Tags:

Using Javascript I'm crudely simulating Brownian motion of particles, but for some reason I don't understand my particles are drifting up and to the left.

The algorithm is pretty straight forward. Each particle is a div and I simply add or subtract a random number from each div's top and left position each round.

I read up on Math.random() a little, and I've tried to use a function that returns a random number from min to max inclussive:

// Returns a random integer between min and max   // Using Math.round() will give you a non-uniform distribution!   function ran(min, max)   {       return Math.floor(Math.random() * (max - min + 1)) + min;   }  

Here is the function for the movement of the particles:

var x, y, $elie, pos, nowX, nowY, i, $that;      function moveIt() {     $("div.spec").each(function(i, v) {         x = ran(-5, 5);         y = ran(-5, 5);         $elie = $(v);         pos = $elie.position();         nowX = pos.left;         nowY = pos.top;            // The min and abs are to keep the particles within a box           // The drift occurs even if I remove min and abs         $elie.css("left", Math.min(Math.abs(nowX + x), 515));         $elie.css("top",  Math.min(Math.abs(nowY + y), 515));      }); } 

And here is how the particles are initially set up an the setInterval started.

$(function() {     $("body").append("<div/>").attr("id","box");     $elie = $("<div/>").attr("class","spec");     // Note that math random is inclussive for 0 and exclussive for Max     for (i = 0; i < 25; ++i)     {         $that = $elie.clone();           $that.css("top", ran(0, 495));         $that.css("left", ran(0, 495));                     $("#box").append($that);                 }               timer = setInterval(moveIt, 60);     $("input").toggle(function() {         clearInterval(timer);         this.value = " Start ";     }, function() {         timer = setInterval(moveIt, 60);                 this.value = " Stop ";                 });         }); 

My problem is that using the min and max from above ( -5, 5 ), all the particles drift up and to the left very fast.

jsFiddle example of drift (-5, 5)

Example of drift even with the removal of .min() and .abs().

To counteract this, I have to use a min and max of -1, 5.

jsFiddle example of no drift (-1, 5)


Here is the CSS for the div all the particles are contained in:

#box {     width:500px;     height:500px;     border:2px #000 solid;     position: relative; } 

Here is the default CSS for each particle:

div.spec {     width:5px;     height:5px;     background-color:#00DDAA;     position:absolute; } 

What is going on? Why does a min and max of -5 and 5 cause an upward and leftward drift?

A test of the random function ran() doesn't seem to show such a persistent negative drift.

jsFiddle example of testing ran()



The ran() function was taken from the MDC Math.random() page.

like image 773
Peter Ajtai Avatar asked Oct 05 '10 22:10

Peter Ajtai


People also ask

Is math random really random?

It may be pointed out that the number returned by Math. random() is a pseudo-random number as no computer can generate a truly random number, that exhibits randomness over all scales and over all sizes of data sets. However, the pseudo-random number generated by Math.

How does math random work internally?

random() Math. 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.

What is math random in Javascript?

The Math. random() function returns a floating-point, pseudo-random number between 0 (inclusive) and 1 (exclusive).

How do you generate a random number 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.


1 Answers

Your mistake is to use

pos = $elie.position(); 

rather than

pos = $elie.offset(); 

This wouldn't have made a difference had they been added to parent div, but your elements aren't properly added to a parent div, they're appended directly to the document body. So your other mistake is this:

$("body").append("<div/>").attr("id","box"); 

If you want the div to have id of 'box', the line should read:

$box = $("<div/>").attr("id","box"); $("body").append($box) 

Otherwise you're actually giving "body" the id of "box"

EDIT:

The most efficient way to append the div would be the following (as noted by this post):

$(document.createElement('div')).appendTo('body').attr('id', 'box') 
like image 92
Herman Schaaf Avatar answered Oct 26 '22 08:10

Herman Schaaf