
731 文字
4 分
PHPのmicrotimeの精度によるmt_srandへの影響
PHP5.3以下を使っていて、microtime()を元に乱数を生成している人は注意!
オフィシャルサイトのサンプルコード通りだとシードがランダムになりません。
PHPのユニットテストで確率を計算しているときに、「なかなか数字が分散しない」と思って調べました。
<?php// seed with microsecondsfunction make_seed(){ list($usec, $sec) = explode(' ', microtime()); return (float) $sec + ((float) $usec * 100000);}
while (true) { var_dump(make_seed());}PHP5.2.14
これはやばい。
int(54)int(54)int(54)int(54)int(54)int(54)int(54)int(54)int(54)int(54)int(54)int(54)int(54)int(54)int(54)int(54)int(54)int(54)int(54)int(54)int(54)int(54)int(54)int(54)int(54)int(54)int(54)int(54)int(54)int(54)int(54)int(52)int(52)int(52)int(52)int(52)int(52)int(52)int(52)int(52)int(52)int(52)int(52)int(52)int(52)int(52)int(52)int(52)int(52)int(52)int(52)int(52)int(52)int(52)int(52)int(52)int(52)int(52)int(52)int(52)int(52)int(52)int(52)int(52)int(52)int(52)int(52)int(52)int(52)int(52)int(52)int(52)int(52)int(52)int(52)int(52)PHP5.3.15
あんまり分散しない。。。
int(30)int(52)int(14)int(4)int(32)int(32)int(41)int(17)int(17)int(86)int(26)int(26)int(32)int(32)int(40)int(37)int(37)int(17)int(59)int(59)int(38)int(38)int(92)int(26)int(26)int(21)int(74)int(74)int(13)int(13)int(24)int(12)int(12)int(86)int(88)int(88)int(82)int(92)int(92)int(21)int(21)int(32)int(26)int(26)int(13)int(96)int(96)int(53)int(53)int(65)int(74)int(74)int(21)int(21)int(2)int(52)int(52)int(29)int(45)int(45)int(85)int(85)int(95)int(38)int(38)int(90)int(90)int(90)int(2)int(2)int(38)int(33)int(33)int(96)int(2)int(2)int(32)int(15)int(15)int(7)int(7)int(83)int(16)int(16)int(2)int(50)int(50)int(20)int(20)int(85)int(30)int(30)int(40)int(19)int(19)int(3)int(3)int(13)int(52)int(52)int(95)int(50)int(50)int(79)int(83)PHP5.4.12
これは良い。
int(13)int(62)int(10)int(35)int(60)int(62)int(59)int(20)int(99)int(46)int(88)int(99)int(15)int(75)int(43)int(79)int(47)int(96)int(39)int(28)int(29)int(32)int(22)int(1)int(77)int(70)int(6)int(36)int(74)int(84)int(87)int(65)int(77)int(34)int(15)int(47)int(22)int(84)int(40)int(19)int(8)int(91)int(5)int(67)int(89)int(79)int(40)int(91)int(17)int(95)int(72)int(59)int(14)int(85)int(25)int(50)int(51)int(46)int(18)int(46)int(79)int(73)int(3)int(78)int(17)int(51)int(86)int(19)int(48)int(34)int(41)int(6)int(20)int(71)int(79)int(49)int(30)int(87)int(30)int(57)int(53)int(90)int(43)int(54)int(80)int(46)int(90)int(44)int(33)int(55)int(10)int(9)int(84)microtime関数のμタイム部分の精度が悪いのが原因ですなー。たぶん。
でも、PHPのソースコードは差分無かった。なので、実行環境の違いかも知れないなー。
追記
PHPでは乱数発生に置いて以下のような問題がある。参考記事
PHPにおける乱数発生の実装は、長らく問題とされてきました。例えば、以下のような問題です。
- メルセンヌツイスタ(1996年に発表された疑似乱数発生器)がいまだに利用されている
- 状態がグローバルな領域に保持されている(メルセンヌツイスタの利用に由来)
- 奇数ばかりが出るなどランダム性が不完全である
最後のはやばいような気がするので検証するコードを書いてみましたが、顕著ではないのかもしれません。
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode characters
| <?php | |
| $result = [ | |
| 0 => 0, | |
| 1 => 0 | |
| ]; | |
| for ($i = 0 ; $i < 100000000 ; $i++) { | |
| $rand_number = mt_rand(); | |
| $result[$rand_number%2]++; | |
| } | |
| print_r($result); |
乱数生成機に偏りがあるとなると、プログラム上で表現されるバランスにクリティカルな影響が出てしまいます。特に、ゲームやカジノなどの確率がビジネスロジックの根底の要素として存在する場合。
PHPの乱数処理に関してより詳細な記事がありました。

参考までに、GPTの回答。

Win, Mac対応のソフトウェアでブルーライト対策
SSL_connect returned=1 errno=0 state=SSLv3 read server certificate B: certificate verify failed
関連記事
この記事が役に立ったら
GitHub Sponsorsで応援できます



