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年に発表された疑似乱数発生器)がいまだに利用されている
- 状態がグローバルな領域に保持されている(メルセンヌツイスタの利用に由来)
- 奇数ばかりが出るなどランダム性が不完全である
最後のはやばいような気がするので検証するコードを書いてみましたが、顕著ではないのかもしれません。
https://gist.github.com/matsubo/516201c7a7e8973a55f18825500e2929
乱数生成機に偏りがあるとなると、プログラム上で表現されるバランスにクリティカルな影響が出てしまいます。特に、ゲームやカジノなどの確率がビジネスロジックの根底の要素として存在する場合。
PHPの乱数処理に関してより詳細な記事がありました。
https://zenn.dev/zeriyoshi/articles/abd808d1c6d31b
参考までに、GPTの回答。

PHPのmicrotimeの精度によるmt_srandへの影響
https://blog.teraren.com/posts/php-mt-rand-microtime/ Win, Mac対応のソフトウェアでブルーライト対策
SSL_connect returned=1 errno=0 state=SSLv3 read server certificate B: certificate verify failed