Comment générer des nombres «aléatoires» mais aussi «uniques»?

Comment sont générés les nombres aléatoires? Comment des langues telles que Java, etc. génèrent-elles des nombres aléatoires, en particulier comment cela est fait pour les GUID? J’ai trouvé que des algorithmes comme le générateur de pseudo-nombre aléatoire utilisent des valeurs initiales.

Mais j’ai besoin de créer un programme de nombre aléatoire, dans lequel un nombre ne se répète jamais, même si le système est redémarré, etc. Je pensais que j’avais besoin de stocker les valeurs n’importe où pour pouvoir vérifier si le nombre se répète ou non, mais ce sera trop complexe quand la liste ira au-delà des limites.

Premièrement: si on garantit que le nombre ne se répète jamais, ce n’est pas très aléatoire.

Deuxièmement: il y a beaucoup d’ algorithmes PRNG .

METTRE À JOUR:

Troisièmement: il existe un RFC IETF pour les UUID (ce que MS appelle des GUID), mais vous devez reconnaître que les UID (U | G) ne sont pas sécurisés sur le plan cryptographique, si cela vous préoccupe.

MISE À JOUR 2:

Si vous voulez réellement utiliser quelque chose comme ceci dans le code de production (pas uniquement pour votre propre édification), veuillez utiliser une bibliothèque préexistante. C’est le genre de code qui contient presque des bogues subtils si vous ne l’avez jamais fait auparavant (ou même si vous l’avez fait).

MISE À JOUR 3:

Voici la documentation pour le GUID de .NET

Il y a beaucoup de façons de générer des nombres aléatoires. Cela se fait généralement avec un appel système / bibliothèque qui utilise un générateur de pseudo-numéros avec une graine comme vous l’avez déjà décrit.

Mais, il existe d’autres moyens d’obtenir des nombres aléatoires qui impliquent du matériel spécialisé pour obtenir de vrais nombres aléatoires. Je connais des sites de poker qui utilisent ce type de matériel. C’est très intéressant de lire comment ils le font.

La plupart des générateurs de nombres aléatoires ont un moyen de réinitialiser “au hasard” la valeur de départ. (Parfois appelé randomize).

Si cela n’est pas possible, vous pouvez également utiliser l’horloge système pour initialiser la graine.

Vous pouvez utiliser cet exemple de code: http://xkcd.com/221/ . Vous pouvez également utiliser ce livre: http://www.amazon.com/Million-Random-Digits-Normal-Deviates/dp/0833030477

Mais sérieusement, ne l’implémentez pas vous-même, utilisez une bibliothèque existante. Vous ne pouvez pas être la première personne à faire cela.

En ce qui concerne spécifiquement Java:

  • java.util.Random utilise un générateur de congruence linéaire , ce qui n’est pas très bon
  • java.util.UUID#randomUUID() utilise java.security.SecureRandom , une interface pour divers RNG sécurisés sur le plan cryptographique – la valeur par défaut est basée sur SHA-1, je crois.
  • Les UUID / GUID ne sont pas nécessairement aléatoires
  • Il est facile de trouver des implémentations de RNG sur le net qui sont bien meilleures que java.util.Random , telles que Mersenne Twister ou multiply-with-carry

Je comprends que vous cherchiez un moyen de générer un nombre aléatoire en utilisant C #. Si oui, RNGCryptoServiceProvider est ce que vous recherchez.

[MODIFIER]

Si vous générez un nombre d’octets assez long à l’aide de RNGCryptoServiceProvider, il est probable qu’il soit unique, mais il n’y a pas de garantie. En théorie, les vrais nombres aléatoires ne signifient pas être uniques. Vous lancez un dé 2 fois et vous pouvez avoir la tête à la fois mais ils sont toujours aléatoires. VRAI ALÉATOIRE!

J’imagine que pour appliquer la vérification d’être unique, il vous suffit de déployer votre propre mécanisme de conservation de l’historique des numéros générés précédemment.