Генерация уникального 6-значного кода
я генерирую 6-значный код из следующих символов. Они будут использоваться для штамповки наклеек.
Они будут генерироваться партиями по 10 тысяч или меньше (до печати), и я не предполагаю, что когда-либо будет больше 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;
- это твердый подход к генерации код?
- сколько возможных перестановок будет? (6-значный код из пула 21 символов). Извините, математика не моя сильная сторона
6 ответов
21^6 = 85766121 возможностей.
использование БД и хранение используемых значений плохо. Если вы хотите подделать случайность, вы можете использовать следующее:
уменьшить до 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 и случайности. - изменить
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);
}
echo $stamp;
Используется
function myRand($no, $str = "", $chr = 'ACEFHJKMNPRTUVWXY4937') {
$length = strlen($chr);
while($no --) {
$str .= $chr{mt_rand(0, $length- 1)};
}
return $str;
}
Как сказал Баба, создание строки на лету приведет к тоннам столкновений. чем ближе вы подойдете к 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 миллионов кодов!
чтобы сгенерировать их все (что займет некоторое время), посмотрите на выбранный ответ на этот вопрос: алгоритм, который будет принимать числа или слова и найти все возможные комбинации.
У меня была такая же проблема, и я нашел очень впечатляющее решение с открытым исходным кодом:
вы можете взять и использовать его, также стоит посмотреть в исходном коде, чтобы понять, что происходит под капотом.
или... вы можете закодировать username+datetime в md5 и сохранить в базе данных, это наверняка создаст уникальный код;)