【问题标题】:PHP - Is rand(1,1000) = 1000 as probable as rand(1,1000) = rand(1,1000)?PHP - rand(1,1000) = 1000 和 rand(1,1000) = rand(1,1000) 一样吗?
【发布时间】:2009-08-16 15:13:26
【问题描述】:

PHP是这样实现随机数生成的吗?

假设我想计算是或否。每次我有一定的概率百分比(比如:这个例子中的 0.05%)。

我愿意:

$possibilities = 100 / $probabilityPercentage; //$possibilities = 2000
$yes = rand(1,$possibilities);

$yesCheck = $possiblities;            //OPTION 1
$yesCheck = rand(1,$possibilities);   //OPTION 2


($yesCheck == $yes) ? return true : return false;

这两种方法的结果是否相同?

【问题讨论】:

    标签: php random


    【解决方案1】:

    让数据自己说话。

    代码

    vinko@parrot:~$ more rand.php
    <?php
    
    $randrandsum = 0;
    $randconstsum = 0;
    $count = 20;
    for ($j = 0; $j < $count; $j++) {
            $randrand = 0;
            $randconst = 0;
            for ($i = 0; $i < 10000000; $i++ ){
                    $a = rand(1,1000);
                    $b = rand(1,1000);
                    if ($a == $b) $randrand++;
            }
            for ($i = 0; $i < 10000000; $i++ ){
                    $a = rand(1,1000);
                    $c = 1000;
                    if ($c == $a) $randconst++;
            }
            $randrandsum += $randrand;
            $randconstsum += $randconst;
            print ($j+1)." RAND-RAND: $randrand RAND-CONST: $randconst\n";
    }
    print "AVG RAND-RAND: ".($randrandsum/$count);
    print " AVG RAND-CONST: ".($randconstsum/$count)."\n";
    ?>
    

    试运行

    vinko@parrot:~$ php rand.php
    1 RAND-RAND: 10043 RAND-CONST: 10018
    2 RAND-RAND: 9940 RAND-CONST: 10132
    3 RAND-RAND: 9879 RAND-CONST: 10042
    4 RAND-RAND: 9878 RAND-CONST: 9965
    5 RAND-RAND: 10226 RAND-CONST: 9867
    6 RAND-RAND: 9866 RAND-CONST: 9992
    7 RAND-RAND: 10069 RAND-CONST: 9953
    8 RAND-RAND: 9967 RAND-CONST: 9862
    9 RAND-RAND: 10009 RAND-CONST: 10060
    10 RAND-RAND: 9809 RAND-CONST: 9985
    11 RAND-RAND: 9939 RAND-CONST: 10057
    12 RAND-RAND: 9945 RAND-CONST: 10013
    13 RAND-RAND: 10090 RAND-CONST: 9936
    14 RAND-RAND: 10000 RAND-CONST: 9867
    15 RAND-RAND: 10055 RAND-CONST: 10088
    16 RAND-RAND: 10129 RAND-CONST: 9875
    17 RAND-RAND: 9846 RAND-CONST: 10056
    18 RAND-RAND: 9961 RAND-CONST: 9930
    19 RAND-RAND: 10063 RAND-CONST: 10001
    20 RAND-RAND: 10047 RAND-CONST: 10037
    AVG RAND-RAND: 9988.05 AVG RAND-CONST: 9986.8
    

    鉴于上述结果,我想说的是,出于所有实际目的,这两个选项都是等效的,在两种情况下都给出了预期的 1/1000 结果。

    【讨论】:

    • +1,尽管我必须用dilbert.com/dyn/str_strip/000000000/00000000/0000000/000000/…回答你的“让数据自己说话”
    • 好吧,在这种情况下,两个结果都是预期的 ~1/1000,所以没有气味
    • 这种测试方法确实不正确,因为它总是在每次迭代中调用 rand() 两次。更准确的测试将运行一个循环测试 rand(1,1000)==1000 和第二个循环测试 rand(1,1000)==rand(1,1000)。
    • 尽管正如你所说,两者最终都达到预期的 1/1000 的事实减轻了这种担忧。
    • 很好的测试!我认为这回答了我的问题。不过,我很好奇更好的测试;)
    【解决方案2】:

    是的,rand(1,1000) = 1000 的概率与 rand(1,1000) = rand(1,1000) 一样。

    想象一下掷两个骰子。在你滚动第一个之后,第二个在滚动时等于第一个的概率是多少? 1/6。

    现在写下 1 到 6 之间的数字并掷骰子。骰子和你刚才写的一样的概率是多少? 1/6。

    【讨论】:

    • 很好的解释,但我无法确定掷一次骰子并让它匹配一个数字是否更有可能然后掷两次(或掷两个骰子)并使其显示同一个号码……
    • 我不同意这个答案。虽然第一句话对于真正的随机事件是正确的,但计算机上的随机数生成器通常并不是真正随机的。事实上,如果你使用线性同余生成器,几乎可以肯定两个连续的数字是相同的(需要取模)。
    【解决方案3】:

    如果随机数生成器是真正随机的,那么两种方法都会产生相同的结果。然而,计算机随机数生成器并不完美。我怀疑这些缺陷是否足够重要,但确定的唯一方法是尝试它——尽可能长时间地运行测试,看看是否与它应该存在的偏差。您至少需要数百万个随机数。

    【讨论】:

    • +1 考虑到大多数基于计算机的“随机”数字生成器的非随机性。
    【解决方案4】:

    这并不能直接解决您的问题,但您可能想查看 mt_rand() 。 PHP 文档指出:

    许多旧的随机数生成器 libcs​​ 有可疑或未知的 特点,速度很慢。经过 默认情况下,PHP 使用 libc 随机 带有 rand() 的数字生成器 功能。 mt_rand() 函数是一个 直接替换这个。它用 一个已知的随机数生成器 使用 » Mersenne 的特征 Twister,这将产生随机 数字比什么快四倍 libc rand() 提供的平均水平。

    来自http://www.php.net/manual/en/function.mt-rand.php

    【讨论】:

      【解决方案5】:

      与大多数随机生成器的工作方式一样,输出并不是真正随机的,而是基于一种算法,该算法应该使返回的值看起来是随机的和分布的。基于此,如果您有两个完全不相关的“随机生成器”,我认为您实际上连续两次获得相同数字的真实概率甚至低于现实世界。

      编辑:话虽如此,我没有任何关于 php 中默认随机生成器如何工作的内部信息。

      【讨论】:

        【解决方案6】:

        选项 1 保证是正确的。

        我认为我在过去学到的概率和统计数据不足以说明选项 2 是否正确。

        然而,我确实知道,如果不运行测试程序,就永远不要相信别人的随机数生成器,以了解它的真正随机性。

        在你的情况下,我会通过这两个选项运行几百万个测试用例,看看选项 2 是否得出与选项 1 相似的统计数据。

        【讨论】:

        • 理论上它们是相同的。
        【解决方案7】:

        理论上,是的,这两个表达式的真实概率完全相同。这是假设 PHP 的随机数生成器实际上是随机的 - 如果不是,那么其中一个比另一个更有可能。

        最好的方法是运行一个实验(数千次迭代),看看会发生什么。

        【讨论】:

        • 这当然不是最好的方法。实验证据充其量只能给出一个指示,即使有 数百万 次迭代。最好的方法是检查算法的确定性方法。
        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2019-01-30
        • 2015-08-02
        • 1970-01-01
        • 2017-10-28
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多