2013年4月14日日曜日

php; shuffle with mt_rand

ペチピーのshuffle()は古いrand()を使い続けて居るけれど、mt_rand()を使うmt_shuffleとかは無いので、
こうすれば良かろ・w・

と言うハナシ。

<?php

$numbers = range(0, 99);

$pred = function($a,$b){return mt_rand() - (mt_getrandmax() >> 1);};
usort($numbers, $pred);

print_r($numbers);

このままだと毎回mt_getrandmax()が呼ばれて1bit右シフトが計算されるので、それはまあ好きに効率向上して使ってね、と。

さて、ここで
「mt_rand(-1,1)でイイジャナイ」
と、思われた方も居られたじゃろうか。ダメ、モッタイナイ・w・

理由は、整数値 [ -1, 0, 1 ] が生成される時、 -1と1の発生確率が等しければその点は問題ありません。しかし、0が生成された時、非安定ソートのusort()の挙動では未定義(というかその瞬間では並べ替えない)です。仕様上は未定義なので実装依存の挙動と言う事にはなりますが、並び替え前の配列の並び方に依存性が生じシャッフル精度が落ちます。

と、言う訳でmt_getrandmax()でmt_rand()の最大値を引っ張りだして半減させて引き算する事で、usortに0が渡される確率を相対的に減らしています。


<おまけ>
ついでにせっかく言語機能にあるので型ヒントも活用。

0 件のコメント:

コメントを投稿