PHP rand()...得到真正的50/50结果?

时间:2009-03-18 14:00:24

标签: php

我想运行一个有两种不同结果的函数,但我希望每个结果真正达到50%。我假设兰德(0,1)是要走的路,但我很好奇,如果这可能有利于一个而不是另一个。获得50/50结果的最佳方法是什么?

感谢。

编辑: 谢谢你们,我不希望它是随机的,我希望结果是101010101而不是111001101.也许我应该用最后一个值输出更新数据库然后返回相反的颜色?

EDIT2: 好的,对不起,我的上次编辑有误导性。我只是为每个用户调用一次函数,并将该值作为cookie分配给用户。我希望每个访问用户在订单1010101中收到1或0。

15 个答案:

答案 0 :(得分:30)

PHP中的

mt_rand()是一个更好的随机数生成器

mt_rand(0,1);

足够,应该产生相当不错的50/50值。

引用mt_rand:

  

许多旧libcs​​的随机数生成器具有可疑或未知的特征并且速度很慢。默认情况下,PHP使用带有rand()函数的libc随机数生成器。 mt_rand()函数是替代它的替代品。

     

它使用具有已知特征的随机数生成器,使用»Mersenne Twister,它将产生比平均libc rand()提供的速度快四倍的随机数。

Bill有一个关于视觉示例的良好链接。我不知道用户在PHP中使用了什么PHP,但是因为他包含了我在我的服务器上托管的代码(使用PHP 5.1.6的Linux)

答案 1 :(得分:10)

对已修改问题的回复:如果您想保持50%的准确率,那么随机性是您想要的最后一件事。为了您的目的,您可能只想为每个新用户(未检测到cookie)分配数据库中的自动编号,然后给偶数用户的一页和奇数用户的另一页(正如RobS在评论中建议的那样)。

if( ($user_id % 2) == 0 )
    // user id is even
else
    // user id is odd

原始答案: PHP的rand()函数不是一个特别好的伪随机数生成器(参见Simple Visual Example)。我建议改为mt_rand()

答案 2 :(得分:2)

两者(rand()和mt_rand())都有50%/ 50%的好几率。

以下是一个例子:

$array1 = array(0,0);
$array2 = array(0,0);

for ($x = 0; $x < 10000; $x++) {
  $array1[mt_rand(0,1)] ++;
  $array2[rand(0,1)] ++;
}

print_r($array1);
print_r($array2);

结果:

Array 1 (mt_rand):
  [0] => 4910
  [1] => 5090
Array 2 (rand):
  [0] => 4970
  [1] => 5030

根据作者的要求,他希望公平分配。所以尝试这样的事情:

$digits = 200;
$array = array_fill(0, $digits/2, 0); 
for ($x = 0; $x < $digits/2; $x++)
  $array[] = 1;
shuffle($array);

平等分配且足够随机。 (Brian建议)

答案 3 :(得分:2)

根据您将使用此编号的特定上下文(例如,基于每个用户,应用程序的生命周期等),您可以将其存储在多个位置,$ _SESSION,数据库值,或者如果范围仅涵盖当前页面,然后您可以将其直接保存在该页面的代码中。

切换值的简便方法是:

$val = 1 - $val;

对于数据库调用:

UPDATE YourTable SET `next_value` = 1 - `next_value`

等...

答案 4 :(得分:1)

根据the php manual rand(0,1)是要走的路。但这一切都取决于随机数发生器有多好。

答案 5 :(得分:1)

没有什么是真正的50/50。如果你想要50/50然后做功能,那么前5个结果是1,其他5个是2等等。

rand用于生成随机数。这意味着它可以连续给出10倍相同的结果,但嘿,这是随机的。

答案 6 :(得分:1)

免责声明:对于您的特定问题,这是一个愚蠢的事情,但如果您坚持不信任您的随机数生成器,以便均匀分布......

当您不相信您的生成器均匀分布时,生成50/50结果的经典算法是以下算法。请注意,此算法更适用于修复随机数而不是伪随机数,实际上可能会使基于mod的结果更糟:

  1. 生成两个随机位A和B.
  2. 如果A == B,转到1
  3. 返回B
  4. 你也可以通过从大量的1和0开始(均匀分布)并随机改组它们来保证平等分配。

答案 7 :(得分:1)

RobS在评论中有一个很好的解决方案,基本上说每个用户都可以得到一个序号,然后使用那个数字%2,你得到0或1,这将决定提供哪个页面。当然,即使这并不能绝对保证给出50/50的比例......这可能是一个奇怪的人数!

同样取决于您如何确定用户,可能值得验证的是,没有某种相关性可以让偶数人更有可能购买......不太可能,但只需要记住一些事情。

有一个替代解决方案,你不必担心奇怪的意外关联:基于你的评论和修改过的问题,你只是想在两个不同页面布局的效果之间进行公平的分析比较是的,您可以简单地将每个页面布局销售额除以随机提供的次数。也就是说,你使用随机数生成器,并跟踪它为服务于页面A提供0次的次数,以及它为服务于页面B提供1次的次数。

假设您在A页上获得了50,000美元的销售额,其中有43次点击,而在B页上的销售额为46,000美元,只有38次点击,您只需进行数学计算......

Page A                      Page B

50000                       46000
----- = 1163 $/hit          ----- = 1211 $/hit
  43                          38

给予B页一点点优势。

答案 8 :(得分:0)

也许您可以尝试mt_rand(0,1)而不是rand(0,1)

答案 9 :(得分:0)

伪随机性永远不会是真正的随机性。基于种子或其他方式的随机数的每次计算都具有某种程度的预先确定性,这种预先确定性可能会或可能不会以明显的方式出现 - 例如迷你模式。你能想到的最好的几乎是50/50。

答案 10 :(得分:0)

虽然它是一个伪随机发生器,它永远不会达到50/50 ...... 看了......关于这里的随机数生成器:http://www.robertnz.net/true_rng.html

答案 11 :(得分:0)

如果您只想要交替1和0:

$n = 0;
$myval = ($n==1 ? $n=0 : $n=1);

答案 12 :(得分:0)

如果你真的希望它在每次迭代时返回相反的值......

function flip() {
    static $truthiness = false;
    $truthiness = !$truthiness;
    return $truthiness;
}

应返回true,false,true,false,true等...

当然,这仅在PHP解释器在调用之间保留在内存中时才有效。

另外,如果您不知道static关键字的作用,请参阅variable scope上的PHP手册条目。

答案 13 :(得分:0)

这个10101010不是随机的,而是一种模式 结果=不是结果

答案 14 :(得分:0)

这是对您对原始帖子的评论的回复:

您的目标是查看哪个版本的页面产生更多销售。

将每个页面随机显示给访问者比为每个连续访问者翻转ABABAB更有意义。

虽然我无法想象你的方法有任何系统偏见的原因,但你不能排除它。 (远程方案:一些跟踪机器人“跟随”用户到你的页面,因此用户1得到A,bot得到B,用户2得到A,bot得到B等等。)

在进行像您正在进行的研究时,实现更好的随机性比确保每个页面在50%的时间内完全显示更为明智。