pourquoi cette méthode retourne-t-elle la même chaîne aléatoire à chaque fois?
Question
Je dois créer un bloc de lignes uniques pour tester un projet différent sur lequel je travaille.
J'ai donc créé un programme simple pour générer une chaîne aléatoire de longueur X.
Le problème est que si je l’appelle une fois, je reçois une chaîne aléatoire. Si je l’appelle de nouveau (dans une boucle for par exemple), je reçois la même chaîne pour l’exécution complète de la boucle.
J'ai l'impression qu'il est mis en cache ou quelque chose du genre, mais je ne savais pas que .net l'avait fait et je suis tout simplement dérouté à ce stade.
code d'appel:
StreamWriter SW = new StreamWriter("c:\\test.txt");
int x = 100;
while (x >0)
{
SW.WriteLine(RandomString(20));
x--;
}
voici la méthode:
private static string RandomString(int Length)
{
StringBuilder sb = new StringBuilder();
Random randomNumber = new Random();
for (int i = 0; i <= Length; ++i)
{
int x = randomNumber.Next(65, 122);
sb.Append(Convert.ToChar(x));
}
return sb.ToString();
}
et voici la sortie:
"VEWMCQ`Fw]TvSFQawYnoB
VEWMCQ`Fw]TvSFQawYnoB
VEWMCQ`Fw]TvSFQawYnoB
VEWMCQ`Fw]TvSFQawYnoB
VEWMCQ`Fw]TvSFQawYnoB
VEWMCQ`Fw]TvSFQawYnoB
..................
VEWMCQ`Fw]TvSFQawYnoB
VEWMCQ`Fw]TvSFQawYnoB
VEWMCQ`Fw]TvSFQawYnoB
VEWMCQ`Fw]TvSFQawYnoB
VEWMCQ`Fw]TvSFQawYnoB"
Alors, qu'est-ce qui donne à penser que Random.next () renverrait toujours un nouveau nombre aléatoire?
La solution
Vous créez les Random
instances trop proches dans le temps. Chaque instance est initialisée à l’aide de l’horloge système. L’horloge n’ayant pas changé, vous obtenez la même séquence de nombres aléatoires à plusieurs reprises.
Créez une seule instance de la using
classe et utilisez-la encore et encore.
Utilisez le mot-clé StreamWriter
pour que le for
soit fermé et supprimé lorsque vous avez terminé. Le code d'une boucle est plus facile à reconnaître si vous utilisez le length
mot clé.
using (StreamWriter SW = new StreamWriter("c:\\test.txt")) {
Random rnd = new Random();
for (int x = 100; x > 0; x--) {
SW.WriteLine(RandomString(rnd, 20));
}
}
La méthode prend l'objet <=> en paramètre.
Utilisez également la longueur pour initialiser StringBuilder avec la capacité correcte, de sorte qu'il ne soit pas nécessaire de réaffecter les ressources pendant la boucle. Utilisez le & Lt; opérateur à la place de < = dans la boucle, sinon vous créerez une chaîne dont la longueur est supérieure à celle spécifiée par le paramètre <=> spécifié.
private static string RandomString(Random rnd, int length) {
StringBuilder sb = new StringBuilder(length);
for (int i = 0; i < length; i++) {
int x = rnd.Next(65, 122);
sb.Append((char)x);
}
return sb.ToString();
}
Autres conseils
Voir la Description du constructeur aléatoire sur MSN, cette partie:
La valeur de départ par défaut est dérivée de l'horloge système et a fini résolution. En conséquence, différents Objets aléatoires créés dans succession proche par un appel à la constructeur par défaut aura valeurs de départ par défaut identiques et, donc, produira des ensembles identiques de nombres aléatoires.
Donc, appelez le constructeur Random () une seule fois au début de votre programme ou utilisez le constructeur Random (int32) et définissez vous-même une graine variable.
Parce que vous créez un nouvel objet aléatoire à chaque appel.
Il suffit de déplacer le randomNumber de la méthode et d'en faire un membre de la classe.
private Random randomNumber = new Random();
private static string RandomString(int Length)
{
StringBuilder sb = new StringBuilder();
//...
}
Tous les logiciels Les générateurs aléatoires sont «pseudo aléatoires», ils produisent une séquence de nombres basée sur une graine (de départ). Avec la même graine, ils produisent la même séquence. Parfois, c'est utile. Si vous voulez que votre programme produise la même séquence à chaque exécution, vous pouvez utiliser new Random(0)
.
Edit: apparemment, la classe .Net Random est auto-ensemencée, je ne le savais pas. C’est donc un problème de synchronisation, comme d’autres l’ont souligné.
déclarer seulement randomNumber une fois
public class MyClass
{
private static Random randomNumber = new Random();
private static string RandomString(int Length)
{
StringBuilder sb = new StringBuilder();
for (int i = 0; i ... Length; ++i)
{
int x = MyClass.randomNumber.Next(65, 122);
sb.Append(Convert.ToChar(x));
}
return sb.ToString();
}
}
Question similaire, beaucoup de réponses:
génération de chaîne aléatoire - deux générées après l'autre donner les mêmes résultats
les valeurs initiales des nombres aléatoires sont toutes identiques en raison de la brièveté du temps nécessaire. En fait, vous recréez le générateur aléatoire avec la même valeur initiale à chaque fois, de sorte que l'appel Next () renvoie la même valeur aléatoire.