2010-07-27 158 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