こういう感じのコードをコピペする。本体は xorshift128、seed から初期値を xorshift32 で設定する (seed をそのまま初期値にすると、近い seed から似たような乱数が始まるので)
Math.random.seed = (function me (s) {
// Xorshift128 (init seed with Xorshift32)
s ^= s << 13; s ^= 2 >>> 17; s ^= s << 5;
let x = 123456789^s;
s ^= s << 13; s ^= 2 >>> 17; s ^= s << 5;
let y = 362436069^s;
s ^= s << 13; s ^= 2 >>> 17; s ^= s << 5;
let z = 521288629^s;
s ^= s << 13; s ^= 2 >>> 17; s ^= s << 5;
let w = 88675123^s;
let t;
Math.random = function () {
t = x ^ (x << 11);
x = y; y = z; z = w;
// >>>0 means 'cast to uint32'
w = ((w ^ (w >>> 19)) ^ (t ^ (t >>> 8)))>>>0;
return w / 0x100000000;
};
Math.random.seed = me;
return me;
})(0);
console.log('seed', 1); //=> seed 1
Math.random.seed(1);
console.log(Math.random()); //=> 0.9905915781855583
console.log(Math.random()); //=> 0.24318050011061132
console.log(Math.random()); //=> 0.00421533826738596
console.log(Math.random()); //=> 0.7972566017415375
console.log('seed', 2); //=> seed 2
Math.random.seed(2);
console.log(Math.random()); //=> 0.620286941062659
console.log(Math.random()); //=> 0.3181322005111724
console.log(Math.random()); //=> 0.7347465583588928
console.log(Math.random()); //=> 0.9439261923544109
console.log('seed', 1); //=> seed 1
Math.random.seed(1);
console.log(Math.random()); //=> 0.9905915781855583
console.log(Math.random()); //=> 0.24318050011061132
console.log(Math.random()); //=> 0.00421533826738596
console.log(Math.random()); //=> 0.7972566017415375
備考
JSの数値型はすべて浮動小数点だけど、ビット演算は32bit整数で行われる。ほとんどの場合、ビット演算の結果は signed 32bit 整数として見たときの値になる。
// not not なのでビット表現は変化しないが、符号ビットが立っているので -1 になる ~~0xffffffff //=> -1
その中で 符号なし右ビットシフト演算子は「The result is an unsigned 32-bit integer.」と書いてあって、珍しい。
// 0ビットシフトなのでビット表現は変化しないが、符号ビットを無視するので 0xffffffff になる (-1)>>>0 //=> 4294967295