2012-09-13 74 views
1

我必须生成大量的唯一键。一个密钥应该由16位数字组成。我想出了以下代码:rand()和一个种子的随机数

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。 然后,我决定产生10个000键,看看有多少重复获得:

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个密钥,我也没有得到任何副本。

+2

什么是cd键?如何使用现有的UUID/GUID生成器? – Evert

+0

@Evert,我想生成一个16位密钥。 32位十六进制数字对于我的需求非常大。 –

+0

测试过的代码,这里没有重复..在PHP 5.3.6上测试过 – dbf

回答

0

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

1

在那里抛出一些uniquid()。

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

+0

谢谢,但我想生成16位数字键。 –

+0

这就是为什么我喜欢“投入”而不是“只是使用”。 '函数getFourDigits(){return substr(uniquid(),0,4)}'......类似的东西 –

+0

uniqid()不适合我的需求。它返回字母和数字。 –