Seeding the random number generator in Javascript

匿名 (未验证) 提交于 2019-12-03 01:58:03

问题:

Is it possible to seed the random number generator (Math.random) in Javascript?

回答1:

No, it is not, but it's fairly easy to write your own generator, or better yet use an existing one. Check out: this related question.

Also, see David Bau's blog for more information on seeding.



回答2:

My other answer represents a more traditional algorithm, but I found Dave Scotese's comment to this answer to be a more eloquent one. Unfortunately, it's pretty slow due to string manipulation.

Here's a version that is about 20 times faster and a bit more precise as well.

var seed = 1; function random() {     var x = Math.sin(seed++) * 10000;     return x - Math.floor(x); }

You can set seed to be any number, just avoid zero (or any multiple of Math.PI).

The elegance of this solution, in my opinion, comes from the lack of any "magic" numbers (besides 10000, which represents about the minimum amount of digits you must throw away to avoid odd patterns - see results with values 10, 100, 1000). Brevity is also nice.

It's a bit slower than Math.random() (by a factor of 2 or 3), but I believe it's about as fast as any other solution written in JavaScript.



回答3:

No, but here's a simple pseudorandom generator I adapted from Wikipedia:

var m_w = 123456789; var m_z = 987654321; var mask = 0xffffffff;  // Takes any integer function seed(i) {     m_w = i;     m_z = 987654321; }  // Returns number between 0 (inclusive) and 1.0 (exclusive), // just like Math.random(). function random() {     m_z = (36969 * (m_z & 65535) + (m_z >> 16)) & mask;     m_w = (18000 * (m_w & 65535) + (m_w >> 16)) & mask;     var result = ((m_z 

EDIT: fixed seed function by making it reset m_z



回答4:

Math.seed = function(s) {     return function() {         s = Math.sin(s) * 10000; return s - Math.floor(s);     }; };  // usage: var random1 = Math.seed(42); var random2 = Math.seed(random1()); Math.random = Math.seed(random2());

This gives you another functionality that Javascript doesn't have: multiple independent random generators. That is especially important if you want to have multiple repeatable simulations running at the same time.



回答5:

Please see Pierre L'Ecuyer's work going back to the late 1980s and early 1990s. There are others as well. Creating a (pseudo) random number generator on your own, if you are not an expert, is pretty dangerous, because there is a high likelihood of either the results not being statistically random or in having a small period. Pierre (and others) have put together some good (pseudo) random number generators that are easy to implement. I use one of his LFSR generators.

https://www.iro.umontreal.ca/~lecuyer/myftp/papers/handstat.pdf

Phil Troy



回答6:

Combining some of the previous answers, this is the seedable random function you are looking for:

Math.seed = function(s) {     var m_w  = s;     var m_z  = 987654321;     var mask = 0xffffffff;      return function() {       m_z = (36969 * (m_z & 65535) + (m_z >> 16)) & mask;       m_w = (18000 * (m_w & 65535) + (m_w >> 16)) & mask;        var result = ((m_z 

Be careful using this one though, I don't believe the distribution of random numbers is very good, it seems to weight towards the 0 to .5 range. At least that was my experience in the random walk visualization I was making.



回答7:

I recommend Alea for fast, high quality randomness (desinged for JS, passes BigCrush test suite):

function Alea(seed) {     if(seed === undefined) {seed = +new Date() + Math.random();}     function Mash() {         var n = 4022871197;         return function(r) {             for(var t, s, u = 0, e = 0.02519603282416938; u 

If you only need a basic PRNG, the Lehmer LCG is much better than the Math.sin method in other answers here:

function LCG(seed) {     function lcg(a) {return a * 48271 % 2147483647}     seed = seed ? lcg(seed) : lcg(Math.random());     return function() {return (seed = lcg(seed)) / 2147483648} }

To use them, you call the main function to init the PRNG with a seed, then call its returned function to generate subsequent numbers:

var rand = Alea("123"); rand(); // 0.4801303152926266

or

var rand = LCG(123); rand(); // 0.45899124443531036


回答8:

To write your own pseudo random generator is quite simple.

The suggestion of Dave Scotese is useful but, as pointed out by others, it is not quite uniformly distributed.

However, it is not because of the integer arguments of sin. It's simply because of the range of sin, which happens to be a one dimensional projection of a circle. If you would take the angle of the circle instead it would be uniform.

So instead of sin(x) use arg(exp(i * x)) / (2 * PI).

If you don't like the linear order, mix it a bit up with xor. The actual factor doesn't matter that much either.

To generate n pseudo random numbers one could use the code:

function psora(k, n) {   var r = Math.PI * (k ^ n)   return r - Math.floor(r) } n = 42; for(k = 0; k 

Please also note that you cannot use pseudo random sequences when real entropy is needed.



回答9:

Many people who need a seedable random-number generator in Javascript these days are using David Bau's seedrandom module.



标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!