Math.random
JavaScript で乱数ジェネレーター ( ) をシードすることは可能ですか?
16 に答える
注: 簡潔さと見た目の優雅さにもかかわらず (というか、そのために)、このアルゴリズムはランダム性の点で決して高品質なものではありません。より良い結果を得るには、たとえばこの回答にリストされているものを探してください。
(元々は、コメントで提示された巧妙なアイデアを別の回答に適応させたものです。)
var seed = 1;
function random() {
var x = Math.sin(seed++) * 10000;
return x - Math.floor(x);
}
任意の数値に設定できますがseed
、ゼロ (または Math.PI の任意の倍数) は避けてください。
私の意見では、このソリューションの優雅さは、「魔法の」数字がないことから来ています(奇妙なパターンを避けるために捨てなければならない最小桁数を表す 10000 以外に - 値10、100、1000の結果を参照してください)。簡潔さもいいです。
Math.random() よりは少し遅いですが (2 倍または 3 倍)、JavaScript で記述された他のソリューションと同じくらい高速だと思います。
いいえ、しかし、これは単純な疑似乱数ジェネレーターであり、ウィキペディアから採用した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;
}
Antti Sykäri のアルゴリズムは素晴らしく、短いものです。Math.random
を呼び出すときに JavaScript を置き換えるバリエーションを最初に作成しました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 にない別の機能が提供されます: 複数の独立したランダム ジェネレーターです。複数の再現可能なシミュレーションを同時に実行したい場合、これは特に重要です。
以前の回答のいくつかを組み合わせると、これはあなたが探しているシード可能なランダム関数です:
Math.seed = function(s) {
var mask = 0xffffffff;
var m_w = (123456789 + s) & mask;
var m_z = (987654321 - s) & mask;
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 << 16) + (m_w & 65535)) >>> 0;
result /= 4294967296;
return result;
}
}
var myRandomFunction = Math.seed(1234);
var randomNumber = myRandomFunction();