113 votes

comment puis-je ensemencer une classe aléatoire pour éviter d'obtenir des valeurs aléatoires en double

J'ai le code suivant dans une méthode statique dans une classe statique

 Random r = new Random();
int randomNumber = r.Next(1,100);
 

J'ai cela dans une boucle et je continue à obtenir le même nombre aléatoire?

des suggestions ici?

316voto

joppiesaus Points 690

Une bonne génération de semences pour moi est:

 Random rand = new Random(Guid.NewGuid().GetHashCode());
 

C'est très aléatoire. La graine est toujours différente car elle est également générée de manière aléatoire.

100voto

Mehrdad Afshari Points 204872

Vous ne devez pas créer un nouveau Random exemple dans une boucle. Essayez quelque chose comme:

var rnd = new Random();
for(int i = 0; i < 100; ++i) 
   Console.WriteLine(rnd.Next(1, 100));

La séquence de nombres aléatoires générés par un seul Random instance est censée être distribuée de manière uniforme. Par la création d'un nouveau Random exemple pour chaque nombre aléatoire dans les successions rapides, vous êtes susceptible de semences avec des valeurs identiques et ont le même nombres aléatoires. Bien sûr, dans ce cas, la séquence produite sera loin d'être une distribution uniforme.

Par souci d'exhaustivité, si vous avez vraiment besoin de réamorcer un Random, vous allez créer une nouvelle instance d' Random avec la nouvelle graine:

rnd = new Random(newSeed);

55voto

Jon Skeet Points 692016

En général, la meilleure idée est d'avoir une seule instance de l' Random par thread - vous ne voulez pas créer une instance régulièrement, vous vous retrouverez avec des répétitions comme vous l'avez vu, et vous ne voulez pas de réutiliser les instances entre les threads comme Random n'est pas thread-safe.

Voici un peu de classe pour vous aider à:

using System;
using System.Threading;

public static class RandomHelper
{
    private static int seedCounter = new Random().Next();

    [ThreadStatic]
    private static Random rng;

    public static Random Instance
    {
        get
        {
            if (rng == null)
            {
                int seed = Interlocked.Increment(ref seedCounter);
                rng = new Random(seed);
            }
            return rng;
        }
    }
}

Vous pouvez ensuite l'utiliser en toute sécurité RandomHelper.Instance à partir de n'importe quel thread. Idéalement, pour la testabilité, vous devriez essayer d'utiliser ce relativement rarement - traiter l'aléatoire comme une dépendance, et de passer l' Random de référence sur les méthodes qui en ont besoin.

Notez que:

  • L' rng champ a l' [ThreadStatic] attribut appliqué à elle, donc c'est effectivement une variable différente pour chaque thread.
  • Nous initialisons seedCounter (une fois) basé sur le temps, mais ensuite il incrément dans un thread-safe manière à chaque fois nous avons besoin d'une nouvelle instance d'un autre thread.

16voto

PPC Points 578

Si, pour une raison quelconque, vous ne pouvez pas utiliser le même Random encore et encore, essayez de l'initialiser avec quelque chose qui change tout le temps, comme le temps lui-même.

 new Random(new System.DateTime().Millisecond).Next();
 

Rappelez-vous que c'est une mauvaise pratique cependant.

2voto

Omidoo Points 142

cela fonctionne pour moi:

 private int GetaRandom()
    {
        Thread.Sleep(1);
        return new Random(DateTime.Now.Millisecond).Next();
    }
 

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X