生成唯一的6位数代码

时间:2013-05-09 23:31:10

标签: php algorithm random permutation

我正在从以下字符生成一个6位数的代码。这些将用于在贴纸上盖章。
它们将分批生成10k或更少(打印前),我不认为总计将超过1-2百万(可能更少)。
生成批量代码后,我将检查现有代码的MySQL数据库,以确保没有重复。

// exclude problem chars: B8G6I1l0OQDS5Z2

$characters = 'ACEFHJKMNPRTUVWXY4937';

$string = '';

for ($i = 0; $i < 6; $i++) {
    $string .= $characters[rand(0, strlen($characters) - 1)];
}   

return $string;
  1. 这是生成代码的可靠方法吗?
  2. 会有多少种可能的排列? (来自21个字符的池中的6位数字代码)。对不起数学不是我的强项

6 个答案:

答案 0 :(得分:12)

21 ^ 6 = 85766121种可能性。

使用数据库并存储使用的值很糟糕。如果您想伪造随机性,可以使用以下内容:

减少到19个可能的数字,并利用p为奇数素数的p ^ k组总是循环的事实。

取7 ^ 19的顺序组,使用生成器co-prime到7 ^ 19(我将选择13 ^ 11,你可以选择任何不能被7整除的东西)。

然后以下工作:

$previous = 0;

function generator($previous)
{

  $generator = pow(13,11);
  $modulus = pow(7,19); //int might be too small
  $possibleChars = "ACEFHJKMNPRTUVWXY49";

  $previous = ($previous + $generator) % $modulus;
  $output='';
  $temp = $previous;

  for($i = 0; $i < 6; $i++) {
    $output += $possibleChars[$temp % 19];
    $temp = $temp / 19;
  }

  return $output;
}

它将循环显示所有可能的值并且看起来有点随机,除非他们去挖掘。一个更安全的替代方案是乘法组,但我已经忘记了我的数学:(

答案 1 :(得分:7)

  • 有很多可能的组合,有或没有重复,所以你的逻辑就足够了
  • 碰撞会很频繁,因为您使用的是rand,请参阅str_shuffle and randomness
  • rand更改为mt_rand
  • 在检查
  • 时,使用memcachedredis等快速存储而不是MySQL

总可能性

21 ^ 6 = 85,766,121

85,766,121应该没问题,要将数据库添加到这一代,请尝试:

示例

$prifix = "stamp.";

$cache = new Memcache();
$cache->addserver("127.0.0.1");

$stamp = myRand(6);
while($cache->get($prifix . $stamp)) {
    $stamp = myRand(6);
}
echo $stamp;

使用的功能

function myRand($no, $str = "", $chr = 'ACEFHJKMNPRTUVWXY4937') {
    $length = strlen($chr);
    while($no --) {
        $str .= $chr{mt_rand(0, $length- 1)};
    }
    return $str;
}

答案 2 :(得分:3)

您将拥有21 ^ 6代码= 85 766 121~ 85.8 百万代码!

要全部生成(这需要一些时间),请查看此问题的选定答案:algorithm that will take numbers or words and find all possible combinations

答案 3 :(得分:3)

巴巴表示,在飞行中生成一根绳子会导致大量的碰撞。越接近已经生成的80万个,获得可用字符串的难度就越大

另一个解决方案可能是生成所有可能的组合,并将它们中的每一个存储在数据库中,并使用一些布尔列字段标记是否已使用行/标记

然后得到其中一个

SELECT * FROM tokens WHERE tokenIsUsed = 0 ORDER BY RAND() LIMIT 0,1

然后将其标记为已使用

UPDATE tokens SET tokenIsUsed = 1 WHERE token = ...

答案 4 :(得分:0)

我遇到了同样的问题,我找到了令人印象深刻的开源解决方案:

http://www.hashids.org/php/

您可以使用它,也值得查看它的源代码,以了解幕后发生的事情。

答案 5 :(得分:-2)

或者......你可以在md5中编码用户名+日期时间并保存到数据库,这肯定会生成一个唯一的代码;)