February 24, 2010

Javascript Random Seed

JavaScript doesn't have a random seed function, which means you've got to roll you own. This little fella works like a charm:

function random(seed) {
if (!seed)
seed = new Date().getTime();
seed = (seed*9301+49297) % 233280;
return seed/(233280.0);
}


Oh, and if you're a fan of Python, check out jash.

13 comments :

pgib said...

What's wrong with Math.random()? Consider:

http://gist.github.com/314841

Ian Wojtowicz said...

Math.random() is fine if you want a different random number each time you execute it. Seeding allows you to create a sequence of random numbers that are the same each time to execute your code (or that is even more random than Math.random() since that method uses time as its seed).

pgib said...

Also, I might be missing something with jash, but Safari's built-in Error Console does the same thing and much, much more...

Ian Wojtowicz said...

Good point about jash. I forgot that Safari has a console.

pgib said...

When would you need to do that? ie. If you want the same sequence of numbers each time, why generate them this way at all?

Ian Wojtowicz said...

I use random seeds all the time. For example, my Illustrator script that scours your harddrive and makes a collage from pieces of all your files. It selects pieces randomly from your files, but I want the same collage every time I run the script. That's when I use a random seed.

Dean Hannotte said...

I understand why the result of this function is replicated when you provide a seed. But when you don't, it just uses the system time. So the first number in the series will always be the same, but the second, third, etc. will be unpredictable. What am I missing?

Does "seed" become a global variable because you haven't declared it using "var"?

Ian Wojtowicz said...

If you don't provide a seed value, the resulting number will be unpredictable (regardless of whether it's the first, second or third call). The point of having a seed value is so that you can produce the same random sequence over and over.

And, yes, the seed variable should probably be declared with as a "var".

Dean Hannotte said...

Sorry to bother you again. I want to generate a sequence of 24 pseudo-randoms that will repeat for 24 hours. I'll use a seed of HHDD where HH is the current hour and DD the current day of the month. That will assure unique results over a year. (The application is very similar to your collage generator.) However I must be making some bad mistakes because my test program, http://www.hannotte.com/Test1.htm, doesn't work at all. Could you take a brief look at it and tell me what I'm doing wrong? Thanks.

pgib said...

Hi Dean,

Because var seed is defined outside the random() function, and inside the function, seed is only set to the current time if it has not already been set to something, repeatedly calling random() without any supplied argument is going to return the same result. So, as far as I can see, your test use is working as expected.

Dean Hannotte said...

Thanks, pgib. I moved the declaration of 'seed' inside the function but I'm still not getting replicable series of pseudo-randoms. Any ideas?

Also, the magic numbers (9301, 49297 and 233280) appear in lots of web pages but I can't find out why. Wikipedia says nothing about them. Is there some explanation of their origin on the web somewhere?

Juho Vepsäläinen said...

This method is a bit problematic in case you need to generate a set of random numbers based on given seed.

In this case it's better to use a more robust solution such as Mersenne Twister.

Simply initializing the twister with some nice seed (var m = new MersenneTwister(123);) and calling it repeatedly (var randomNumber = m.random();) gives the desired result.

Zach Dyer said...

There is a pattern to the random value if you start with 1 you get 0.25 and for every iteration you get an additional 0.04 until you get to 0.97 then it resets to 0.0 and increments in smaller numbers. However with large seed numbers that vary you should get random results as long as the numbers are big and a lot different every time.