Domanda

Devo creare un blocco di linee uniche per testare un diverso progetto su cui sto lavorando.

Quindi ho creato un semplice programma per generare una stringa casuale di lunghezza X.

Il problema è che se lo chiamo una volta, ottengo una stringa casuale, se la chiamo di nuovo (ad esempio in un ciclo for) ottengo la stessa stringa per l'intera esecuzione del ciclo.

Ho la sensazione che venga memorizzato nella cache o qualcosa del genere, ma non sapevo che .net lo ha fatto e sono solo confuso a questo punto.

codice chiamante:

    StreamWriter SW = new StreamWriter("c:\\test.txt");
    int x = 100;
    while (x >0)
    {
        SW.WriteLine(RandomString(20));
        x--;
    }

ecco il metodo:

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();        
}

ed ecco l'output:

"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"

Quindi cosa mi ha fatto pensare che Random.next () avrebbe sempre restituito un nuovo numero casuale?

È stato utile?

Soluzione

Stai creando le Random istanze troppo vicine nel tempo. Ogni istanza viene inizializzata utilizzando l'orologio di sistema e poiché l'orologio non è cambiato, si ottiene ripetutamente la stessa sequenza di numeri casuali.

Crea una singola istanza della classe using e usala più volte.

Utilizzare la parola chiave StreamWriter in modo che for sia chiuso e eliminato al termine. Il codice per un ciclo è più facile da riconoscere se si utilizza la length parola chiave.

using (StreamWriter SW = new StreamWriter("c:\\test.txt")) {
   Random rnd = new Random();
   for (int x = 100; x > 0; x--) {
      SW.WriteLine(RandomString(rnd, 20));
   }
}

Il metodo accetta l'oggetto <=> come parametro.

Inoltre, utilizzare la lunghezza per inizializzare StringBuilder con la capacità corretta, in modo che non debba riallocare durante il ciclo. Usa & Lt; operatore invece di < = nel ciclo, altrimenti creerai una stringa che è un carattere più lungo di quanto specificato dal parametro <=>.

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();        
}

Altri suggerimenti

Vedi Descrizione casuale del costruttore su MSN, questa parte:

  

Da cui deriva il valore seed predefinito   l'orologio di sistema e ha finito   risoluzione. Di conseguenza, diverso   Oggetti casuali che vengono creati in   chiudere la successione con una chiamata al   il costruttore predefinito avrà   valori seed predefiniti identici e,   pertanto, produrrà set identici   di numeri casuali.

Quindi chiama il costruttore Random () solo una volta all'inizio del tuo programma o usa il costruttore Random (int32) e definisci tu stesso un seme variabile.

Perché crei un nuovo oggetto casuale in ogni chiamata.

Basta spostare randomNumber fuori dal metodo e renderlo un membro di classe.

private Random randomNumber = new Random();
private static string RandomString(int Length)
{
    StringBuilder sb = new StringBuilder();
    //...
}

Tutti i software I generatori casuali sono 'pseudo casuali', producono una sequenza di numeri basata su un seme (iniziale). Con lo stesso seme producono la stessa sequenza. A volte questo è utile. Se vuoi produrre il tuo programma per produrre la stessa sequenza ad ogni corsa, puoi usare new Random(0).

Modifica: apparentemente la classe .Net Random è auto-seeding, non lo sapevo. Quindi è un problema di tempistica, come altri hanno sottolineato.

dichiara randomNumber una sola volta



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();        
    }
}

il seme per i numeri casuali è lo stesso a causa del breve tempo impiegato, in effetti ricrea ogni volta il generatore casuale con lo stesso seme, quindi la chiamata Next () restituisce lo stesso valore casuale.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top