2012-09-13 93 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()不適合我的需求。它返回字母和數字。 –