我刚刚在Hacker News上碰到过ComputerGuru的interesting question,似乎没有任何评论可以给出令人信服的答案。
为什么mt_rand(1, PHP_INT_MAX)
总是返回奇数?
我不是原始问题的作者。
http://3v4l.org/dMbat
for ($i=0;$i<10000;$i++)
{
echo mt_rand(1, PHP_INT_MAX)."\n";
}
输出:
8571620074060775425
7401021871338029057
4351677773593444353
1801559362708176897
7848614552286527489
...
最佳答案
此处的PHP_INT_MAX
是263-1(最大64位有符号int)。
但是,mt_rand()
不能处理这么大的值。 Mersenne扭曲程序在内部生成32位字,而PHP的mt_getrandmax()
仅231-1(它丢弃了最高位)。
为了在您请求的min
到max
范围内生成一个值,mt_rand
首先获取0到231-1的随机数,然后使用以下公式对其进行缩放:
x = ((x / (mt_getrandmax() + 1)) * (max - min + 1)) + min;
(请参阅rand.c和php_rand.h的来源。)
基本上,它会盲目地缩放内部生成的数字以适应较大的范围,甚至不会发出警告。乘以适合较大的范围会在低位产生很多零,然后添加
min
(为1)会使结果奇怪。这个问题在十六进制中更为严重,您可以看到每个数字的低32位完全是非随机的:
for ($i = 0; $i < 10000; $i++) {
printf("%016x\n", mt_rand(1, PHP_INT_MAX));
}
输出:
41e0449b00000001
53d33d7c00000001
6ec8855700000001
234140e000000001
13a4581900000001
77547beb00000001
35a0660a00000001
0d0cd44200000001
...
有一个注释in the manual试图警告此问题,尽管它低估了该问题:
(它说它偏向偶数,但是只有当
min
是偶数时,这才是正确的。)关于php - 为什么mt_rand(1,PHP_INT_MAX)总是返回奇数,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/31612082/