8
votes

Générer un code unique à 6 chiffres

Je génère un code à 6 chiffres des caractères suivants. Ceux-ci seront utilisés pour tamponner sur des autocollants.
Ils seront générés par lots de 10 000 ou moins (avant impression) et je n'envisage pas qu'il n'y aura jamais plus de 1-2 millions de dollars (probablement beaucoup moins).
Après avoir généré les lots de codes, je vérifierai la base de données MySQL des codes existants pour vous assurer qu'il n'y a pas de duplicate.

// exclude problem chars: B8G6I1l0OQDS5Z2

$characters = 'ACEFHJKMNPRTUVWXY4937';

$string = '';

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

return $string;


2 commentaires

Il y a quelques bons messages ici sur diverses approches: Stackoverflow.com/questions/1846202/...


Si vous n'avez pas besoin de plus de 8 millions de codes et de codes courts et sans ambiguïtés, une priorité absolue, je dirais que vous avez un bon moyen de le faire.


6 Réponses :


3
votes

Vous auriez 21 codes ^ 6 = 85 766 121 ~ 85,8 millions de codes!

Pour les générer (ce qui prendrait du temps), regardez la réponse sélectionnée à cette question: algorithme qui prendra des chiffres ou des mots et trouveront toutes les combinaisons possibles .


1 commentaires

Vous vous mêlez de votre base et de votre exposant et vous avez gérée votre séparation du chiffre, c'est ~ 86 millions



14
votes

21 ^ 6 = 85766121 Possibilités.

L'utilisation d'un dB et de stockage des valeurs utilisées est mauvaise. Si vous voulez simuler aléatoire, vous pouvez utiliser ce qui suit: p>

Réduisez à 19 numéros possibles et utilisez le fait que des groupes d'ordre p ^ k où p est un capitaine élevé sont toujours cycliques. P >

Prendre le groupe d'ordre 7 ^ 19, en utilisant un générateur co-prime à 7 ^ 19 (je choisirai 13 ^ 11, vous pouvez choisir tout ce qui n'est pas divisible de 7). P>

Alors Les travaux suivants: P>

$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;
}


7 commentaires

Les codes générés doivent être stockés car ils sont associés à des timbres (produits) qui auront des informations associées à eux. Si je génère 10k de codes, alors un mois plus tard 10k, j'ai besoin de vérifier en quelque sorte qu'il n'y a pas de doublons dans ce nouveau lot de 10k.


J'ai posté comment ignorer les doublons, mais si vous stockez des informations supplémentaires de toute façon ignorant cette réponse.


@ Jean-Bernardpellerin php-ized You Code, espérons que cela ne vous dérange pas, veuillez vérifier si tout est allright


Cela sera-t-il unique à chaque fois ou dois-je vérifier cela manuellement? Et je ne veux pas que ce soit de 21 caractères seulement, tout va bien pour moi.


Comment utiliser cette réponse


6 ^ 19 ou 19 ^ 6? 6 n'est pas un peu d'impair, alors je suppose que vous vouliez dire ce dernier. Dans ce cas, votre choix de générateur n'est pas co-prime à celui-ci (19 ^ 11) - 11 ^ 19 semble ok. Je cherchais des codes de 5 caractères et je suis arrivé à cette réponse; J'utilise 23 ^ 5 (supprimé I, O et Q de l'alphabet) en tant que module et 19 ^ 11 pour le générateur qui semble fonctionner pour moi.


il devrait s'agir de $ de sortie. = $ Possisblecharks [$ TEMP% 19];



7
votes
  • Il y a beaucoup de combinaison possible avec ou sans répétition, votre logique serait donc suffisante
  • la collision serait fréquent parce que vous utilisez rand voir str_shauffe et aléatoire .
  • Changer rand à mt_rand
  • Utilisez un stockage rapide comme memcached ou redis pas mySQL lors de la vérification

    possibilité totale xxx

    85,766,121 devrait être correct, pour ajouter de la base de données à cette génération Essayez:

    Exemple xxx

    fonction utilisée xxx


1 commentaires

Merci. 86 moulin suffit. Je vais utiliser votre suggestion de mt_rand. Je ne sais pas comment Memcached peut être utilisé pour vérifier que les codes dans un lot nouvellement généré n'existant pas déjà dans MySQL (contenant tous les lots de codes générés précédemment). À des fins d'impression, j'imagine générer des codes de 10k ou des codes à la fois



3
votes

Comme Baba dit que générer une corde à la volée entraînera des tonnes de collisions. Plus vous allez passer à 80 millions de personnes déjà générées les plus difficiles qu'il deviendrai pour obtenir une chaîne disponible

Une autre solution pourrait être de générer toutes les combinaisons possibles une fois et de stocker chacune d'elles dans la base de données déjà, avec un champ de colonne booléen. qui marque si une rangée / jeton est déjà utilisée ou non p>

puis pour obtenir l'un d'entre eux p> xxx pré>

puis marquez comme déjà utilisé p >

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


2 commentaires

Merci, j'aurais pensé qu'il y aurait eu un coup de performance si vous conservez que 80 combinaisons de moulins, en termes de requêtes, etc. Le code sera recherché non seulement comme log.


Je pense que vous pourriez combiner cette approche avec la génération cyclique de @ Jean-Bernard et faire de votre requête beaucoup rapidement - remplissez la base de données avec toutes les combinaisons d'un ordre quelque peu aléatoire, et chaque fois que vous avez besoin de nouvelles valeurs, vous pouvez les saisir à un temps. Pourrait valoir un essai, de toute façon.



0
votes

J'ai eu le même problème et j'ai trouvé une solution open source très impressionnante:

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

Vous pouvez le prendre et l'utiliser, il vaut également la peine de regarder dans son code source pour comprendre ce qui se passe sous la hotte.


0 commentaires

-2
votes

ou ... Vous pouvez encoder le nom d'utilisateur + DateTime dans MD5 et enregistrer dans la base de données, ceci générera certainement un code unique;)


0 commentaires