🧠

PHP8.2 で登場した乱数生成器を使った 1 〜 100 までの乱数を Seed 値で固定するときの対応表

2023/01/06に公開約7,700字

はじめに

PHP8.2 から乱数生成に関して大きなアップデートがありました.
ランダムな値を生成する Random\Engine というインタフェースがあり,それを用いて乱数を生成する Random\Randomizer というクラスができました.

詳しくは以下の記事が参考になると思います(丸投げ)
https://qiita.com/rana_kualu/items/ab82a9c6dbd2e7c6edd0

また,PHP がネイティブで提供する Engine として,以下の 4 つがあります

  • Random\Engine\Mt19937::class
  • Random\Engine\PcgOneseq128XslRr64::class
  • Random\Engine\Xoshiro256StarStar::class
  • Random\Engine\Secure::class

例えば,1 〜 10 のランダムな整数を生成したい場合次のように書くことができます

$engine = new Random\Engine\Secure();
$randomizer = new Random\Randomizer($engine);
$randomizer->getInt(1, 10);

これら 4 種類の Engine のうち,Secure 以外の 3 つは Seed 値をコンストラクタに渡すことができ,外側から乱数生成をコントロールできます.

$engine = new Random\Engine\Mt19937(3);
$randomizer = new Random\Randomizer($engine);
$randomizer->getInt(1, 10); // seed 値 3 に対応する何かが固定で出てくる

このように Seed 値を固定してやれば,$randomizer->getInt(1, 10) は何度実行しても同じ値を返します.
とはいえ,「この Seed 値を渡せばこの整数が出てくる」みたいな対応表や逆算方法はありません.

本記事では,差し当たり 1 〜 100 までの整数を生成する Seed 値を,3 種類の各 Engine 毎に愚直に求めましたので,その方法と実際に出した対応表を紹介します.

Seed 値と生成される整数の対応表の算出方法

例として,Random\Engine\Mt19937::class を使った場合のコードを示します.

// Random\Engine\Mt19937 で 1 ~ 100 の値を固定で出すシード値を計算
$map = [];
for ($seed = 0; $seed < 10000; ++$seed) {
    $randomInt = (new \Random\Randomizer(new \Random\Engine\Mt19937($seed)))->getInt(1, 100);
    if (!isset($map[$randomInt])) { // まだ出てなければ整数と Seed 値の組を保存
        $map[$randomInt] = $seed;
    }
    // 100 まで集まったらループ終了
    if (count($map) === 100) {
        break;
    }
}
ksort($map); // 1 -> 100 の順になるように並び替える

要は,とりあえず 10000 回くらいぶん回してみて虱潰しに探していくという方法です.
1 〜 100 までのランダムな整数なので,試行回数 10000 回くらい回せばきっと全種類出てくれるよね,という楽観的な発想です.

実際,php-src の実装でも,同じような方法を使ってロジックのテストを書いている箇所がありました.

対応表

乱数を固定したテストをするときにでもお役立てください

Random\Engine\Mt19937

整数 Seed 値
1 111
2 60
3 248
4 120
5 50
6 132
7 18
8 45
9 249
10 76
11 95
12 5
13 201
14 116
15 24
16 7
17 66
18 35
19 13
20 67
21 160
22 149
23 126
24 8
25 105
26 145
27 31
28 80
29 48
30 56
31 4
32 20
33 15
34 46
35 242
36 14
37 41
38 10
39 40
40 27
41 75
42 11
43 42
44 247
45 0
46 1
47 114
48 153
49 2
50 26
51 51
52 82
53 241
54 21
55 74
56 47
57 165
58 142
59 91
60 17
61 226
62 688
63 141
64 12
65 118
66 36
67 115
68 131
69 33
70 130
71 9
72 89
73 63
74 78
75 70
76 81
77 150
78 28
79 62
80 90
81 72
82 16
83 73
84 437
85 88
86 29
87 3
88 129
89 43
90 22
91 49
92 23
93 25
94 59
95 124
96 103
97 139
98 30
99 98
100 68

Random\Engine\PcgOneseq128XslRr64

整数 Seed 値
1 43
2 319
3 76
4 14
5 4
6 69
7 53
8 25
9 15
10 16
11 162
12 174
13 112
14 126
15 42
16 80
17 101
18 73
19 9
20 24
21 11
22 113
23 275
24 160
25 37
26 44
27 71
28 32
29 39
30 46
31 31
32 195
33 143
34 36
35 286
36 66
37 22
38 6
39 19
40 78
41 662
42 20
43 116
44 28
45 56
46 75
47 7
48 2
49 191
50 21
51 34
52 335
53 74
54 45
55 57
56 13
57 89
58 94
59 345
60 154
61 68
62 5
63 49
64 361
65 314
66 123
67 29
68 52
69 82
70 35
71 72
72 139
73 3
74 0
75 8
76 96
77 237
78 41
79 61
80 23
81 60
82 324
83 95
84 48
85 18
86 150
87 30
88 165
89 122
90 183
91 118
92 50
93 47
94 528
95 1
96 10
97 97
98 362
99 393
100 117

Random\Engine\Xoshiro256StarStar

整数 Seed 値
1 33
2 30
3 304
4 52
5 20
6 27
7 73
8 11
9 31
10 87
11 7
12 92
13 74
14 47
15 42
16 8
17 365
18 10
19 153
20 234
21 292
22 49
23 116
24 39
25 81
26 65
27 13
28 178
29 37
30 235
31 121
32 23
33 276
34 106
35 44
36 72
37 298
38 129
39 114
40 282
41 98
42 107
43 150
44 291
45 43
46 118
47 255
48 97
49 32
50 12
51 143
52 148
53 145
54 5
55 41
56 34
57 38
58 6
59 17
60 64
61 93
62 51
63 19
64 90
65 68
66 18
67 26
68 25
69 3
70 58
71 180
72 2
73 251
74 21
75 151
76 392
77 59
78 132
79 103
80 61
81 89
82 232
83 104
84 15
85 69
86 162
87 117
88 256
89 141
90 91
91 200
92 4
93 0
94 14
95 57
96 229
97 36
98 1
99 22
100 182

スペシャルサンクス

今回の方法をアドバイスしてくれた mpyw さん

GitHubで編集を提案

Discussion

ログインするとコメントできます