JavaScript でシードを使用して乱数を生成する
-
シードと
SFC32
を使用して乱数を生成する -
Seed と
Mulberry32
を使用して乱数を生成する -
Seed と
Xoshiro128**
を使用して乱数を生成する -
シードと
JSF
を使用して乱数を生成する -
seedrandom.js
を使用して乱数を生成する
この記事では、シードを使用して PRNG から乱数を生成する方法について説明します。 一方、PRNG のシードのエントロピーが高いことを確認するのがベスト プラクティスです。
したがって、ハッシュ関数を使用してシードを生成します。 その後、シードを PRNG に渡します。
シードと SFC32
を使用して乱数を生成する
SFC32
または Simple Fast Counter は、PractRand
からの高速な PRNG (ほとんどが C) であり、128 ビット状態の JavaScript で実装されており、非常に高速です。 SFC32
では、乱数を生成するために少なくとも 1つのシードが必要です。
MurmurHash3 の JavaScript 実装であるハッシュ関数を使用して、このシードを生成します。これには、シードを生成するための初期文字列が必要です。 その結果、文字列を渡します。
次のコードでは、シードを生成し、乱数を返す SFC32
に渡します。
コード:
// Define the Murmur3Hash function
function MurmurHash3(string) {
let i = 0;
for (i, hash = 1779033703 ^ string.length; i < string.length; i++) {
let bitwise_xor_from_character = hash ^ string.charCodeAt(i);
hash = Math.imul(bitwise_xor_from_character, 3432918353);
hash = hash << 13 | hash >>> 19;
}
return () => {
// Return the hash that you can use as a seed
hash = Math.imul(hash ^ (hash >>> 16), 2246822507);
hash = Math.imul(hash ^ (hash >>> 13), 3266489909);
return (hash ^= hash >>> 16) >>> 0;
}
}
function SimpleFastCounter32(seed_1, seed_2, seed_3, seed_4) {
return () => {
seed_1 >>>= 0;
seed_2 >>>= 0;
seed_3 >>>= 0;
seed_4 >>>= 0;
let cast32 = (seed_1 + seed_2) | 0;
seed_1 = seed_2 ^ seed_2 >>> 9;
seed_2 = seed_3 + (seed_3 << 3) | 0;
seed_3 = (seed_3 << 21 | seed_3 >>> 11);
seed_4 = seed_4 + 1 | 0;
cast32 = cast32 + seed_4 | 0;
seed_3 = seed_3 + cast32 | 0;
return (cast32 >>> 0) / 4294967296;
}
}
let generate_seed = MurmurHash3('String for the Seed Key');
let random_number = SimpleFastCounter32(generate_seed(), generate_seed());
console.log(random_number());
console.log(random_number());
出力:
0.837073584087193
0.3599331611767411
Seed と Mulberry32
を使用して乱数を生成する
Mulberry32
も PRNG ですが、SFC32
よりもコード構造が単純です。 少なくともシードが必要な SFC32
とは対照的です。
MurmurHash3 を使用して、文字列を使用してシードを生成します。 次の例では、for ループと Mulberry32
を使用して 5つの乱数を生成します。
コード:
// Define the Murmur3Hash function
function MurmurHash3(string) {
let i = 0;
for (i, hash = 1779033703 ^ string.length; i < string.length; i++) {
let bitwise_xor_from_character = hash ^ string.charCodeAt(i);
hash = Math.imul(bitwise_xor_from_character, 3432918353);
hash = hash << 13 | hash >>> 19;
}
return () => {
// Return the hash that you can use as a seed
hash = Math.imul(hash ^ (hash >>> 16), 2246822507);
hash = Math.imul(hash ^ (hash >>> 13), 3266489909);
return (hash ^= hash >>> 16) >>> 0;
}
}
function Mulberry32(string) {
return () => {
let for_bit32_mul = string += 0x6D2B79F5;
let cast32_one = for_bit32_mul ^ for_bit32_mul >>> 15;
let cast32_two = for_bit32_mul | 1;
for_bit32_mul = Math.imul(cast32_one, cast32_two);
for_bit32_mul ^= for_bit32_mul +
Math.imul(for_bit32_mul ^ for_bit32_mul >>> 7, for_bit32_mul | 61);
return ((for_bit32_mul ^ for_bit32_mul >>> 14) >>> 0) / 4294967296;
}
}
let generate_seed = MurmurHash3('String for the Seed Key');
let random_number = Mulberry32(generate_seed());
for (let i = 0; i < 5; i++) {
console.log(random_number());
}
出力:
0.13532060221768916
0.8630009586922824
0.53870237339288
0.5237146227154881
0.8748106376733631
Seed と Xoshiro128**
を使用して乱数を生成する
Vagna 教授と Blackman は、Xoshiro128**
ジェネレーターを開発しました。 xorshift128
は Xorshift
PRNG のファミリーであり、最速の PRNG です。
SFC32
と同様に、Xoshiro128**
は、乱数を生成する前に少なくともシードを取得できます。 次のスニペットでは、必要なシードを MurmiurHash3 で作成しました。
コード:
// Define the Murmur3Hash function
function MurmurHash3(string) {
let i = 0;
for (i, hash = 1779033703 ^ string.length; i < string.length; i++) {
let bitwise_xor_from_character = hash ^ string.charCodeAt(i);
hash = Math.imul(bitwise_xor_from_character, 3432918353);
hash = hash << 13 | hash >>> 19;
}
return () => {
// Return the hash that you can use as a seed
hash = Math.imul(hash ^ (hash >>> 16), 2246822507);
hash = Math.imul(hash ^ (hash >>> 13), 3266489909);
return (hash ^= hash >>> 16) >>> 0;
}
}
function Xoshiro128_twostar(seed_1, seed_2, seed_3, seed_4) {
return () => {
let t = seed_2 << 9, y = seed_1 * 5;
y = (y << 7 | y >>> 25) * 9;
seed_3 ^= seed_1;
seed_4 ^= seed_2;
seed_2 ^= seed_3;
seed_1 ^= seed_4;
seed_3 ^= t;
seed_4 = seed_4 << 11 | seed_4 >>> 21;
return (y >>> 0) / 4294967296;
}
}
let generate_seed = MurmurHash3('String for the Seed Key');
let random_number = Xoshiro128_twostar(generate_seed(), generate_seed());
console.log(random_number());
出力:
0.6150987280998379
シードと JSF
を使用して乱数を生成する
Bob Jenkins は、高速ジェネレーターである Jenkins Small Fast (JSF) ジェネレーターを作成しました。 ただし、≪SFC32≫に比べれば速くはない。
JSF
のコードを観察すると、SFC32
との類似性に気付くでしょう。 JSF
は乱数を生成する前に複数のシードを取ることができます。
次のコードでは、シードと JSF
を使用して 10 個の乱数を生成します。
コード:
// Define the Murmur3Hash function
function MurmurHash3(string) {
let i = 0;
for (i, hash = 1779033703 ^ string.length; i < string.length; i++) {
let bitwise_xor_from_character = hash ^ string.charCodeAt(i);
hash = Math.imul(bitwise_xor_from_character, 3432918353);
hash = hash << 13 | hash >>> 19;
}
return () => {
// Return the hash that you can use as a seed
hash = Math.imul(hash ^ (hash >>> 16), 2246822507);
hash = Math.imul(hash ^ (hash >>> 13), 3266489909);
return (hash ^= hash >>> 16) >>> 0;
}
}
function JenkinsSimpleFast32(seed_1, seed_2, seed_3, seed_4) {
return () => {
seed_1 |= 0;
seed_2 |= 0;
seed_3 |= 0;
seed_4 |= 0;
let t = seed_1 - (seed_2 << 27 | seed_2 >>> 5) | 0;
seed_1 = seed_2 ^ (seed_3 << 17 | seed_3 >>> 15);
seed_2 = seed_3 + seed_4 | 0;
seed_3 = seed_4 + t | 0;
seed_4 = seed_1 + t | 0;
return (seed_4 >>> 0) / 4294967296;
}
}
let generate_seed = MurmurHash3('String for the Seed Key');
let random_number = JenkinsSimpleFast32(generate_seed(), generate_seed());
for (let i = 0; i < 10; i++) {
console.log(random_number());
}
出力:
0.513338076416403
0.4737987464759499
0.5743723993655294
0.4811882192734629
0.07753282226622105
0.11416710214689374
0.1270705321803689
0.15759771666489542
0.16906401910819113
0.6846413582097739
seedrandom.js
を使用して乱数を生成する
seedrandom.js
は、David Bau がシード乱数ジェネレータ (RNG) 用に設計したライブラリで、NPM と CDNJS で利用できます。 この記事では、CDNJS を使用します。
Seedrandom.js
を使用する場合は、次の点に注意してください。
new Math.seedrandom('seed key')
を使用してseedrandom
を初期化します。Seedrandom
のquick()
関数を使用して、32 ビットの乱数を生成できます。- Seedrandom.js の
int32()
関数は、32 ビットの符号付き整数を返します。 - 引数なしで
seedrandom
を呼び出すと、自動シードされた ARC4 ベースの PRNG が作成されます。 自動シード処理では、累積されたローカル エントロピーなどの値が使用されます。 Seedrandom
は 2 番目の引数としてオブジェクトを取ることができます。 このオブジェクトは{entropy: true}
であり、結果は予測できません。new
キーワードなしでMath.seedrandom
を呼び出すと、デフォルトのMath.random()
が置き換えられます。 代わりはnew Math.seedrandom()
です。
この例では、CDNJS から seedrandom.js
をインポートしました。 その後、シードを使用して乱数を生成するために使用します。
コード:
<body>
<script src="https://cdnjs.cloudflare.com/ajax/libs/seedrandom/3.0.5/seedrandom.min.js"></script>
<script>
let generate_random_number = new Math.seedrandom('Johnson');
console.log(generate_random_number());
</script>
</body>
出力:
0.08103389758898699
シードを蓄積されたエントロピーと混ぜることができます。 seedrandom
の 2 番目の引数として {entropy: true}
を渡す必要があります。
コード:
<body>
<script src="https://cdnjs.cloudflare.com/ajax/libs/seedrandom/3.0.5/seedrandom.min.js"></script>
<script>
let generate_random_number = new Math.seedrandom('Antananarivo', { entropy: true });
for (let i = 0; i < 5; i++) {
console.log(generate_random_number());
}
</script>
</body>
出力:
0.8478730572111559
0.963664252064149
0.6002684820777331
0.4026776455839767
0.7579996916288508
さらに、quick()
と int32()
はランダムな 32 ビット乱数を返します。 前者は float を返し、後者は符号付き整数を返します。
コード:
<body>
<script src="https://cdnjs.cloudflare.com/ajax/libs/seedrandom/3.0.5/seedrandom.min.js"></script>
<script>
let generate_random_number = new Math.seedrandom('DavidBau');
console.log("With quick():", generate_random_number.quick());
console.log("With int32():", generate_random_number.int32());
</script>
</body>
出力:
With quick(): 0.249648863915354
With int32(): -550219731
Habdul Hazeez is a technical writer with amazing research skills. He can connect the dots, and make sense of data that are scattered across different media.
LinkedIn