带有rand()和一个种子的随机数

时间:2012-09-13 21:49:30

标签: php

我必须生成大量唯一键。一个密钥应由16位数组成。我想出了以下代码:

function make_seed()
{
    list($usec, $sec) = explode(' ', microtime());
    return (float) $sec + ((float) $usec * 100000);
}
function generate_4_digits(){
    $randval = rand(100, 9999);
    if($randval < 1000){
        $randval = '0'.$randval;
    }
    return (string)$randval;
}
function generate_cdkey(){
    return generate_4_digits() . '-' . generate_4_digits() . '-' . generate_4_digits() . '-' . generate_4_digits();
}


srand(make_seed());
echo generate_cdkey();

结果很有希望,6114-0461-7825-1604。 然后我决定生成10000个密钥,看看我得到了多少重复:

srand(make_seed());
$keys = array();
$duplicates = array();
for($i = 0; $i < 10000; $i++){
    $new_key = generate_cdkey();
    if(in_array($new_key, $keys)){
        $duplicates[] = $new_key;
    }
    $keys[] = $new_key;
}
$keys_length = count($keys);
var_dump($duplicates);
echo '<pre>';
for($i = 0; $i < $keys_length; $i++){
    echo $keys[$i] . "\n";
}
echo '</pre>';

第一次运行时我得到了1807个重复项,这非常令人失望。但是,对于我后来的每一次运行我都非常惊讶,我得到相同数量的重复!?当我仔细查看生成的密钥时,我意识到最后1807个密钥与第一个密钥完全相同。所以我可以生成8193而没有一个副本?!这是如此接近2 ^ 13 ?!我们能否得出结论rand()适合生成maz 2 ^ 13个唯一数字?但为什么呢?

我将代码更改为使用mt_rand(),即使生成50 000个密钥也没有重复。

3 个答案:

答案 0 :(得分:1)

在那里扔一些uniquid()。

http://www.php.net/manual/en/function.uniqid.php

答案 1 :(得分:1)

这可能是您正在寻找的更多内容。 openssl_random_pseudo_bytes ( int $length [, bool &$crypto_strong ] )

答案 2 :(得分:0)

这可能与srand的行为有关。检查重复项时,您只对所有10000个键运行一次srand。也许srand只产生足够的~2 ^ 13键?您使用的是什么PHP版本?因为不再需要4.2.0 srand,但是如果你无论如何都要调用它,它会自动停止为脚本的其余部分执行它。