まぁ、$min < $max でないときの挙動を気にする必要はないのだけれど、mt_rand(0, -100)と入れた場合も、エラーはでずに、-25 とか -86 とか返って来てうまく動いているようにみえる。けど、乱数のレンジが微妙。
サンプルコードを書いてみる。
<?php list(, $min, $max) = $argv; foreach (range($min, $max) as $i) { $x[$i] = 0; } for ($i = 0; $i < 10000; ++$i) { $x[mt_rand($min, $max)]++; } print_r($x); ?>
list()とかrange()とかべんりですね。
で、指定のmin、maxから10,000回コールの分布をみてみる。
正常! ($min < $max)
ちゃんと0から10まで均等に分布してます
$ php rand.php 0 10
Array
(
[0] => 949
[1] => 912
[2] => 898
[3] => 910
[4] => 870
[5] => 940
[6] => 914
[7] => 930
[8] => 899
[9] => 921
[10] => 857
)
$ php rand.php -5 5
Array
(
[-5] => 875
[-4] => 889
[-3] => 889
[-2] => 904
[-1] => 905
[0] => 904
[1] => 900
[2] => 903
[3] => 957
[4] => 927
[5] => 947
)
異常
$ php rand.php 0 -10
Array
(
[0] => 1120
[-1] => 1121
[-2] => 1108
[-3] => 1070
[-4] => 1117
[-5] => 1122
[-6] => 1089
[-7] => 1121
[-8] => 1132
[-9] => 0
[-10] => 0
)
$ php rand.php 5 -5
Array
(
[5] => 1065
[4] => 1161
[3] => 1114
[2] => 1100
[1] => 1077
[0] => 1125
[-1] => 1090
[-2] => 1089
[-3] => 1179
[-4] => 0
[-5] => 0
)$max側の2つが表れてないことがわかります。
$ php rand.php 10 8
Array
(
[10] => 10000
[9] => 0
[8] => 0
)で、$i == mt_rand($i, $i - 2)になりそう。
ソース
ソースコードでは、一旦、 (long) (php_mt_rand(TSRMLS_C) >> 1); で、0 〜 PHP_MT_RAND_MAX の乱数を生成して、範囲が指定されている場合に、
#define RAND_RANGE(__n, __min, __max, __tmax) \
(__n) = (__min) + (long) ((double) ( (double) (__max) - (__min) + 1.0) * ((__n) / ((__tmax) + 1.0)))のマクロで範囲に変換してるのですが、算数力が低下していて読み解くのめんどくさくなって挫折。
追記
mt_rand([int $min, int $max])で $min > $max のときの挙動 (理由解説編) - おぎろぐはてなで、このマクロの動きと、それによって起こる上のような問題について解説してます。