2010-07-27 160 views
0

我建立的「代理ID的」名單在我的數據庫具有以下要求:隨機ID /數生成PHP

  1. 的ID必須是9個位數(僅限數字)
  2. 的ID不得包含超過3個相同的數字。
  3. 的ID可能不包含多於2相同數量的連續的(即887766551;不能具有888 ..)

到目前爲止,我有部分1向下固體但正在與上述圖2和3掙扎。我的代碼如下。

function createRandomAGTNO() { 
    srand ((double) microtime()*1000000); 
    $random_agtno = rand(100000000,900000000); 
    return $random_agtno; 
} 

// Usage 
$NEWAGTNO = createRandomAGTNO(); 

任何想法?

+4

一個微型優化...將您的'rand'調用從'100112233'調整爲'998877665'(最低和最高可能的匹配,因此您切出很多不必要的嘗試)... – ircmaxell 2010-07-27 20:55:45

+0

+1好心思ircmaxell! .. – Poni 2010-07-27 21:02:27

回答

7
  1. 重新種上一樣,每次調用的RNG,除非你想完全吹你的隨機數的安全。
  2. 除非您的PHP很舊,否則您可能根本不需要重新播種RNG,因爲PHP在啓動時爲您播種,並且極少有情況下您需要用其中一種替換種子自己選擇。
  3. 如果它可用,請使用mt_rand而不是rand。我的例子將使用mt_rand

至於其餘 - 你可能會想出一個非常巧妙的線性範圍數字映射到你想要的形式的數字,但讓我們蠻力而不是。這是其中一種情況,運行時間的理論上限是無限的,但預計運行時間是有限的且相當小,所以不要太擔心。

function createRandomAGTNO() { 
    do { 
    $agt_no = mt_rand(100000000,900000000); 
    $valid = true; 
    if (preg_match('/(\d)\1\1/', $agt_no)) 
     $valid = false; // Same digit three times consecutively 
    elseif (preg_match('/(\d).*?\1.*?\1.*?\1/', $agt_no)) 
     $valid = false; // Same digit four times in string 
    } while ($valid === false); 
    return $agt_no; 
} 
+0

我的直覺告訴eiww由於循環中的正則表達式。但是再次,它們都是輕量級的正則表達式,並且對於每個「try」節省多個'rand'調用(甚至是'array_rand'和'shuffle'函數多次在內部調用它)...所以它似乎不是幾乎和本能所暗示的一樣糟糕(實際上,它看起來相當不錯)... +1 ... – ircmaxell 2010-07-27 20:51:50

+0

我想說數學上做它會是最快的。正則表達式無法擊敗它。 – Poni 2010-07-27 20:54:01

+0

試試吧。正則表達式的解決方案平均每次運行時間爲0.00006秒,平均值爲0.00017秒(我的數據大概是0.00015)。噢,平均每次運行超過100000次。所以就剪切速度而言,它看起來像正則表達式需要蛋糕... – ircmaxell 2010-07-27 21:05:31

1

對於第二個條件,可以創建這樣

$a = array(0,0,1,1,2,2,3,3.....,9,9); 

陣列和得到的隨機元素:array_rand()(見說明書)得到數位,將其追加到您的ID和由除去從源數組值在索引處取消設置。

一般來說,這種解決也第三個條件,但這種方法排除了所有的ID與可能的和可接受的三位

+1

['shuffle'](http://us2.php.net/manual/en/function.shuffle.php)和['array_shift'](http://us2.php.net/manual/en/ function.array-shift.php)/ ['array_pop'](http://us2.php.net/manual/en/function.array-pop.php)是'array_rand'和不設置索引的可行替代方案。 – Charles 2010-07-27 20:21:34

0

想到的第一個解決方案是一個遞歸函數,它只是簡單地測試你的三點要求,並重新啓動,如果其中任意三個失敗。不是最有效的解決方案,但它會工作。我在下面寫了一個未經測試的版本。不能沒有錯誤地運行,但你應該從中獲得基本的想法。

function createRandomAGTNO(){ 
    srand ((double) microtime()*1000000); 
    $random_agtno = rand(100000000,900000000); 

    $random_agtno_array = explode('', $random_agtno); 

    foreach($random_agtno_array as $raa_index => $raa){ 
    if($raa == $random_agtno_array[$raa_index + 1] && raa == $random_agtno_array[$raa_index + 2]) createRandomAGTNO(); 

    $dup_match = array_search($raa, $random_agtno_array); 
    if($dup_match){ 
     unset($random_agtno_array[$dup_match]); 
     if(array_search($raa, $random_agtno_array)) createRandomAGTNO(); 
    }; 
    } 

    return $random_agtno; 
} 
0

試試這個代碼:

<?php 
function createRandomAGTNO() { 
    //srand ((double) microtime()*1000000); 
    $digits = array(1, 2, 3, 4, 5, 6, 7, 8, 9, 0 ,1, 2, 3, 4, 5, 6, 7, 8, 9, 0); 
    shuffle($digits); 
    $random_agtno = 0; 
    for($i = 0; $i < 9; $i++) 
    { 
     if($i == 0) 
     { 
      while($digits[0] == 0) 
       shuffle($digits); 
     } 
     /*if($i >= 2) 
     { 
      while(($random_agtno % 100) == $digits[0]) 
       shuffle($digits); 
     }*/ 
     $random_agtno *= 10; 
     $random_agtno += $digits[0]; 
     array_splice($digits, 0, 1); 
    } 
    return $random_agtno; 
} 

for($i = 0; $i < 1000; $i++) 
{ 
    $NEWAGTNO = createRandomAGTNO(); 
    echo "<p>"; 
    echo $NEWAGTNO; 
    echo "</p>"; 
} 
?> 

祝你好運!

編輯: 刪除了對srand()的調用並註釋掉了「if($ i> = 2)」代碼,這在這裏是不可能的。

+0

這裏的優勢在於: 1)你沒有使用字符串/字符,但只有數字。 2)使用內置於PHP中的shuffle()命令,因此速度很快。我不認爲你真的需要使用srand(),現在我看到了.. :) – Poni 2010-07-27 20:42:13

+0

嗨ircmaxell,我真的不明白你的意思。檢查更新的代碼。在1000個數字中查找違反規則的輸出,因爲我找不到。 – Poni 2010-07-27 20:51:08

+0

至於三位數字 - 如果此代碼從上面的數組中獲取數字我們如何得到相同數字的3倍? – Poni 2010-07-27 20:52:26