是否有可能在JavaScript中播种随机数生成器(Math.random) ?


当前回答

对于一个固定的种子有一个简单的方法:

function fixedrandom(p){
    const seed = 43758.5453123;
    return (Math.abs(Math.sin(p)) * seed)%1;
}

其他回答

对于一个固定的种子有一个简单的方法:

function fixedrandom(p){
    const seed = 43758.5453123;
    return (Math.abs(Math.sin(p)) * seed)%1;
}

Antti Sykäri的算法很好,很短。我最初做了一个变种来取代JavaScript的Math。当你调用Math.seed(s)时是随机的,但随后Jason评论说返回函数会更好:

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());

这为您提供了JavaScript没有的另一个功能:多个独立的随机生成器。如果您希望同时运行多个可重复的模拟,这一点尤其重要。

编写自己的伪随机生成器非常简单。

戴夫·斯科塞斯的建议是有用的,但正如其他人指出的那样,它并不是完全均匀分布的。

然而,这并不是因为sin的整数参数。这只是因为sin的范围,恰好是一个圆的一维投影。如果取圆的角度,它就会是均匀的。

所以用arg(exp(i * x)) / (2 * PI)代替sin(x)

如果你不喜欢线性顺序,可以把它和异或混合一下。实际因素也没有那么重要。

要生成n个伪随机数,可以使用以下代码:

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

还请注意,当需要真实熵时,不能使用伪随机序列。

SIN(id + seed)是一个非常有趣的替代RANDOM函数,不能像SQLite一样播种:

https://stackoverflow.com/a/75089040/7776828

没有,但这里有一个简单的伪随机生成器,一个我从维基百科改编的Multiply-with-carry的实现(已经被删除了):

var m_w = 123456789;
var m_z = 987654321;
var mask = 0xffffffff;

// Takes any integer
function seed(i) {
    m_w = (123456789 + i) & mask;
    m_z = (987654321 - i) & mask;
}

// 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 << 16) + (m_w & 65535)) >>> 0;
    result /= 4294967296;
    return result;
}