我正在从以下字符生成 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;
这是生成代码的可靠方法吗?
会有多少种可能的排列?(来自 21 个字符池的 6 位数字代码)。对不起,数学不是我的强项
21 ^ 6 = 85766121 可能性。
使用 DB 并存储使用的值是不好的。如果你想伪造随机性,你可以使用以下内容:
减少到 19 个可能的数字,并利用 p ^ k 阶组的事实,其中 p 是一个奇素数总是循环的。
以 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;
}
它会循环遍历所有可能的值,看起来有点随机,除非他们去挖掘。一个更安全的选择是乘法组,但我已经忘记了我的数学:(
有很多可能的组合,有或没有重复,所以你的逻辑就足够了
碰撞会很频繁,因为您使用的是rand
,请参阅str_shuffle and randomness。
rand
tomt_rand
检查时使用快速存储,如memcached
或redis
而不是 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);
}
ec $stamp;
使用的函数
function myRand($no, $str = "", $chr = 'ACEFHJKMNPRTUVWXY4937') {
$length = strlen($chr);
while($no --) {
$str .= $chr{mt_rand(0, $length- 1)};
}
return $str;
}
正如 Baba 所说,在飞行中生成字符串将导致大量碰撞。您越接近已经生成的 80 百万个,就越难获得可用的字符串
另一种解决方案可能是生成所有可能的组合一次,并将它们存储在数据库中,一些布尔列字段标记是否已经使用行 / 令牌
然后得到其中一个
SELECT * FROM tokens WHERE tokenIsUsed = 0 ORDER BY RAND() LIMIT 0,1
然后将其标记为已使用
UPDATE tokens SET tokenIsUsed = 1 WHERE token = ...
您将有 21 ^ 6 个代码 = 85 766 121 〜85.8百万个代码!
要生成它们(这将需要一些时间),请查看此问题的选定答案:algorithm that will take numbers or words and find all possible combinations。
本站系公益性非盈利分享网址,本文来自用户投稿,不代表边看边学立场,如若转载,请注明出处
评论列表(28条)