PHP mt_rand 真的是随机的还是可能有偏见?
Is PHP mt_rand really random or possibly biased?
我在我的网站上做了两个基本的 A-B-C 测试,类似
if(mt_rand(0,2) == 0){
//THROW IN RE HERE
}elseif(mt_rand(0,2) == 1){
//THROW IN LR HERE
}else{
//THROW IN LB HERE
}
我原以为这三种情况发生的频率相同(占所有网页浏览量的 33.3%)。但是,展示次数(由 Google Adsense 衡量)显示出非常不同的分布。有趣的是,两个测试(下面的两个图表)都显示出相似的模式:LB 出现最多,然后是 RE,然后是 LR。
样本量有数千,因此随机发生这种情况的可能性实际上为零。
我是不是误会了mr_rand()?有人知道它是否经过适当测试吗?这些奇怪的图案还能怎么出现?
我不确定您是如何通过 Google Adsense 收集数据的。您是否通过传递一些自定义变量来依赖 Google 分析?如果是这样,肯定有其他因素导致与 PHP.
无关的偏差
为了测试均匀随机分布,我们可以 运行 在 PHP 中进行这样的测试。
$test = [0,0,0];
for($i = 0; $i < 100000; $i++) {
$rand = mt_rand(0,2);
$test[$rand]++;
}
var_dump($test);
哪个应该给你这样的结果...
array(3) {
[0]=>
int(33288)
[1]=>
int(33394)
[2]=>
int(33318)
}
这表示您正在寻找超过 10 万次迭代的 33% 均匀分布。
请务必注意,mt_rand()
的实现是 PRNG(伪随机数生成器)而不是 CSPRNG(加密安全伪随机数生成器)。意思是,它不太适合加密目的,但可以很好地满足其他 PRNG 需求。它基于 Mersenne Twister,因为它比 libc rand()
更快。尽管我认为您在此处发现的数据中的任何问题都可能不是 PHP 实施 mt_rand()
的直接结果。
您正在 运行 宁 mt_rand 测试两次。您有选项 0、1 和 2。如果测试为 0,则抛出 RE。如果不是,(即它是 1 或 2),您 运行 再次进行相同的测试(再次使用选项 0、1 和 2)。在那里测试 1,如果是,则抛出 LR。如果不是(它是 0 或 2)你扔 LB。如果您需要,我可以进一步解释..
$number = mt_rand(0,2);
switch ($number){
case 0:
//do re
break;
case 1:
//do lr
break;
case 2:
//do lb
break;
}
或者这也可以完成工作
if(mt_rand(0,2) == 0){
//THROW IN RE HERE
}elseif(mt_rand(0,1) == 1){ //we've stripped RE out, no longer deciding from 3 options
//THROW IN LR HERE
}else{
//THROW IN LB HERE
}
我在我的网站上做了两个基本的 A-B-C 测试,类似
if(mt_rand(0,2) == 0){
//THROW IN RE HERE
}elseif(mt_rand(0,2) == 1){
//THROW IN LR HERE
}else{
//THROW IN LB HERE
}
我原以为这三种情况发生的频率相同(占所有网页浏览量的 33.3%)。但是,展示次数(由 Google Adsense 衡量)显示出非常不同的分布。有趣的是,两个测试(下面的两个图表)都显示出相似的模式:LB 出现最多,然后是 RE,然后是 LR。
样本量有数千,因此随机发生这种情况的可能性实际上为零。
我是不是误会了mr_rand()?有人知道它是否经过适当测试吗?这些奇怪的图案还能怎么出现?
我不确定您是如何通过 Google Adsense 收集数据的。您是否通过传递一些自定义变量来依赖 Google 分析?如果是这样,肯定有其他因素导致与 PHP.
无关的偏差为了测试均匀随机分布,我们可以 运行 在 PHP 中进行这样的测试。
$test = [0,0,0];
for($i = 0; $i < 100000; $i++) {
$rand = mt_rand(0,2);
$test[$rand]++;
}
var_dump($test);
哪个应该给你这样的结果...
array(3) { [0]=> int(33288) [1]=> int(33394) [2]=> int(33318) }
这表示您正在寻找超过 10 万次迭代的 33% 均匀分布。
请务必注意,mt_rand()
的实现是 PRNG(伪随机数生成器)而不是 CSPRNG(加密安全伪随机数生成器)。意思是,它不太适合加密目的,但可以很好地满足其他 PRNG 需求。它基于 Mersenne Twister,因为它比 libc rand()
更快。尽管我认为您在此处发现的数据中的任何问题都可能不是 PHP 实施 mt_rand()
的直接结果。
您正在 运行 宁 mt_rand 测试两次。您有选项 0、1 和 2。如果测试为 0,则抛出 RE。如果不是,(即它是 1 或 2),您 运行 再次进行相同的测试(再次使用选项 0、1 和 2)。在那里测试 1,如果是,则抛出 LR。如果不是(它是 0 或 2)你扔 LB。如果您需要,我可以进一步解释..
$number = mt_rand(0,2);
switch ($number){
case 0:
//do re
break;
case 1:
//do lr
break;
case 2:
//do lb
break;
}
或者这也可以完成工作
if(mt_rand(0,2) == 0){
//THROW IN RE HERE
}elseif(mt_rand(0,1) == 1){ //we've stripped RE out, no longer deciding from 3 options
//THROW IN LR HERE
}else{
//THROW IN LB HERE
}