zver
zver

Reputation: 33

Javascript Math.random() returning very similar values

So I have elements that are position: absolute and then I use Math.random() to set their left:#random and top:#random position.

However a very weird thing is happening. It should be completely random, thus they should be placed completely randomly. However time and time again, they are placed very closely together. Instead of being spread apart.

enter image description here

however you can clearly see, their positions are indeed random: enter image description here

Here is the code I use to generate them:

const Clouds = function(props) {
    const clouds = []
    for (let i = 0; i < props.cloudNum; i++) {
        const style = {
            position: 'absolute',
            height: 50 * props.cloudSize + 'px',
            top: Math.random() * 100 + '%',
            left: Math.random() * 100 + '%',
        }
        clouds.push(<Cloud key={i} style={style} />)
    }
    return <div className={props.side}>{clouds}</div>
}

is there a temporal component to Math.random, and because they are generated in sequence their random numbers are similar?

Upvotes: 1

Views: 819

Answers (3)

kb05
kb05

Reputation: 69

In fact, although they look like similar numbers they are not (remember that you are multiplying by 100), this means that your space of random numbers goes from 0 to 100 (since the decimals in the drawing barely have value, as is the case that you ask).

Keep in mind that if your space is 100 clouds only generating 13 clouds there is more than a 50% probability that two clouds occupy the same position by the birthday problem.

https://en.wikipedia.org/wiki/Birthday_problem

Upvotes: 2

Mos&#232; Raguzzini
Mos&#232; Raguzzini

Reputation: 15821

It's a coincidence that you get similar value. Try as many times as you want with my snippet to test it your own.

Note that my objects are much smaller than yours, not having elements overlapping give a better sense of randomness. IMHO, if you are generating clouds (depends on purposes) it could be better to use perlin noise

const container = document.getElementById('container');

const Clouds = function() {
   
    for (let i = 0; i <10; i++) {        
         let myCloud = document.createElement("div");
        myCloud.style.height = '15px';
                myCloud.style.width = '15px';
        myCloud.style.position = 'absolute';
        myCloud.style.background =  '#fff';
        myCloud.style.border = '1px solid #ccc';
        myCloud.style.left = Math.random()*100+'%';
        myCloud.style.top = Math.random()*100+'%';
        container.appendChild(myCloud);
    }
   
}

function generate() {
 container.innerHTML = '';
 Clouds();
}
#container {
  position: absolute;
  top: 0;
  right: 0;
  left: 0;
  bottom: 0;
  background: red;
}

button {
position: absolute;
z-index: 999;
}
<div id="container"></div>
<button onClick="generate()">Generate</button>

Upvotes: 0

Jack Bashford
Jack Bashford

Reputation: 44087

There's no temporal component - it's just generated by the system. Here's a good thread explaining it. The random algorithm depends on the JavaScript engine (there's a V8 answer in that thread) but the function always produces a floating-point number between 0 and 1 inclusive. It's an incredibly large coincidence that your code yielded two numbers that close.

Upvotes: -1

Related Questions