mt_rand関数を使って、ランダムな値を作りたいけど、
その中で、一部の値を除外したい時って、
あるじゃないですか。
例えば、1~10の間のランダムな数値を作りたいが、
5だけは出ないようにしたい。とか。
でも、どうやらmt_rand関数には、
そういうオプションはありそうにない。
https://www.php.net/manual/ja/function.mt-rand.php
(「random_intを使いましょう」的な警告は一旦置いときます。)
そういう機能のあるランダム値を返す関数も、
調べても見つからないので、
ちょっと簡単に作ってみました。
<?php function mt_rand_except( int $min, int $max, int $except ) : int { do { $num = mt_rand($min, $max); } while ($num == $except); return $num; } print mt_rand_except( 1, 10, 5 );
ただし、これで動作確認しても、
本当に5が除外されてるのかわかりにくいですw
なので、以前作った、
mt_rand関数のばらつきを調べるプログラムを使って、
動作確認してみます。
<?php $parameter = 10000; // mt_randを実行する回数 $rand_min = 1; // MIN $rand_max = 10; // MAX $except_num = 5; // 除外したい数字 $buf = array_pad( array(), $rand_max - $rand_min + 1, 0 ); // 出た数字のカウントを格納する配列 for($i = 1; $i < $parameter; $i++){ $sample = mt_rand_except( $rand_min, $rand_max, $except_num ); $buf[$sample - $rand_min]++; } function mt_rand_except( int $min, int $max, int $except ) : int { do { $num = mt_rand($min, $max); } while ($num == $except); return $num; } ?> <!DOCTYPE html> <head> <title>mt_rand test</title> </head> <body> <table border="1"> <tr> <th>No.</th> <th>times</th> <th>rate</th> </tr> <?php for($i = $rand_min; $i <= $rand_max; $i++){ print("<tr align=\"right\"><td>".$i."</td>"); print("<td>".$buf[$i-$rand_min]."回</td>"); printf("<td>%.2f%%</td></tr>\n",$buf[$i-$rand_min]/$parameter*100); } ?> </table> </body> </html>
●結果
10000回やっても、5が1回も出てません。
OKですね。
ちなみに、
除外したい数字が複数ある場合は、
配列でも渡せるように関数を修正しました。
$except_num = [2, 3, 5]; // 除外したい数字の配列 ... function mt_rand_except( int $min, int $max, $except ) : int { if (gettype($except) == 'array'){ do { $num = mt_rand($min, $max); } while (in_array($num, $except)); } else { do { $num = mt_rand($min, $max); } while ($num == $except); } return $num; }
●結果
はい。
ちゃんと2、3、5が除外されて返されています。