web-dev-qa-db-fra.com

Comment générer un nombre unique de 8 chiffres?

J'utilise ce code pour générer un numéro unique à 8 chiffres.

byte[] buffer = Guid.NewGuid().ToByteArray();
return BitConverter.ToUInt32(buffer, 8).ToString();

Ce code génère-t-il vraiment un numéro unique ou peut-il répéter le même numéro?

15
dev

Un GUID n'est pas simplement un nombre aléatoire; il est composé de segments. Certains segments ne changeront pas du tout si le guide est généré sur le même ordinateur. En n'utilisant que 64 bits des 128 bits d'origine, vous rompez la structure du GUID et probablement le caractère unique du nombre généré.

Cette question a plus d’informations sur l’unicité des astuces, vérifiez ce lien ainsi que sur les raisons pour lesquelles il est mauvais d’utiliser une partie seulement d’un guide si vous avez besoin d’un numéro unique.

Si vous devez limiter la duplication à un minimum absolu, un compteur incrémentiel vous donnera ce dont vous avez besoin. Si votre application utilise plusieurs threads ou processus, il peut être difficile (voire impossible) d'implémenter un compteur correctement.

C’est le domaine dans lequel les écrans ont été conçus pour être uniques sur plusieurs machines. Ainsi, si l'unicité des machines est une exigence, vous devez utiliser des guids. Le guid entier.

9
Marnix van Valen

Toute séquence aléatoire est liée à certaines collisions. C'est juste une question de quand. En utilisant la formule du paradoxe de l'anniversaire, avec 100 000 000 de valeurs possibles (8 chiffres), la probabilité de collision avec seulement 10 000 éléments est d'environ 40% et de 99% avec 30 000 éléments. ( voir ici pour une calculatrice ).

Si vous avez vraiment besoin d'une séquence aléatoire, vous ne devez pas utiliser de GUID à cette fin. Les GUID ont une structure très spécifique et ne doivent être pris que dans leur ensemble. Il est assez facile de créer un générateur de séquence aléatoire de 8 chiffres. Cela devrait vous donner une séquence de 8 chiffres: 

 public string Get8Digits()
 {
   var bytes = new byte[4];
   var rng = RandomNumberGenerator.Create();
   rng.GetBytes(bytes);
   uint random = BitConverter.ToUInt32(bytes, 0) % 100000000;
   return String.Format("{0:D8}", random);
 }

Vous pouvez également prendre RandomNumberGenerator et le placer quelque part pour éviter d’en créer un nouveau à chaque fois.

9
Can Gencer

Voici une autre version

public static string GetFormNumber()
    {
        byte[] buffer = Guid.NewGuid().ToByteArray();
        var FormNumber = BitConverter.ToUInt32(buffer, 0) ^ BitConverter.ToUInt32(buffer, 4) ^ BitConverter.ToUInt32(buffer, 8) ^ BitConverter.ToUInt32(buffer, 12);
        return FormNumber.ToString("X");

    }

ça assure d'être unique!

4
Kamran Qadir

Ma première réponse n'a pas abordé le problème de l'unicité. Mon deuxième fait:

static int counter;
public static int GetUniqueNumber()
{ 
    return counter++; 
}

Si vous souhaitez avoir des numéros uniques lors des redémarrages d'applications, vous devez conserver la valeur counter à une base de données ou ailleurs après chaque appel GetUniqueNumber.

3
usr

Cette méthode générera une chaîne aléatoire, elle ne s'appuie pas sur la méthode Random et est bien meilleure que l'approche guid:

public static string gen_Digits(int length)
{
    var rndDigits = new System.Text.StringBuilder().Insert(0, "0123456789", length).ToString().ToCharArray();
    return string.Join("", rndDigits.OrderBy(o => Guid.NewGuid()).Take(length));
}

vous pouvez augmenter la longueur pour réduire les risques de collision, mais pour avoir une séquence unique à 100%, vous devez conserver les anciennes valeurs générées et vérifier si la valeur nouvellement créée est unique.

2
Chtiwi Malek

La plage de valeurs est trop petite. Un compteur incrémentiel est la meilleure solution, comme dans un système ERP - vous définissez le premier numéro de client sur 1000 et le suivant sur 1001, 1002, ..., 99999999. Sinon, si vous obtenez un nombre aléatoire (ou une partie du GUID) à partir de ceux-ci, vous frappez à nouveau le même nombre. En fonction de votre application, tôt ou tard, mais il est certain que cela se produira plus tôt que de simplement les parcourir.

2
Vladislav Zorov

Si vous voulez un nombre unique compris entre 10000000 et 99999999, démarrez un entier compris entre 10000000 et commencez simplement à l'incrémenter. Générer des nombres séquentiellement ordonnés n’est pas moins aléatoire que n’importe quelle autre séquence générée, et bien plus facile à générer.

1
Kevin Hsu
System.Threading.Thread.Sleep(1);
long code = (long)DateTime.UtcNow.Subtract(new DateTime(2018, 1, 1, 0, 0, 0, DateTimeKind.Utc)).TotalMilliseconds;

OR

System.Threading.Thread.Sleep(1000);
long code = (long)DateTime.UtcNow.Subtract(new DateTime(2018, 1, 1, 0, 0, 0, DateTimeKind.Utc)).TotalSeconds;
0
karim fereidooni

Si vous exprimez le non par une combinaison de jour (2 chiffres), heure (2 chiffres), minute (2 chiffres), seconde (chiffre) et année (4 chiffres), le numéro sera alors de 12 chiffres mais toujours unique.

 DateTime _now = DateTime.Now;
 string _dd = _now.ToString("dd"); //
 string _mm = _now.ToString("MM");
 string _yy = _now.ToString("yyyy");
 string _hh = _now.Hour.ToString();
 string _min = _now.Minute.ToString();
 string _ss = _now.Second.ToString();

 string _uniqueId= _dd+ _hh+ _mm+_min+_ss + _yy;
0
agileDev