Pregunta

Necesito crear un bloque de líneas únicas para probar un proyecto diferente en el que estoy trabajando.

Entonces creé un programa simple para generar una cadena aleatoria de longitud X.

El problema es que si lo llamo una vez, obtengo una cadena aleatoria, si lo llamo nuevamente (en un bucle for, por ejemplo) obtengo la misma cadena durante toda la ejecución del bucle.

Tengo la sensación de que se está almacenando en caché o algo así, pero no sabía que .net hacía eso y estoy confundido en este punto.

código de llamada:

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

aquí está el método:

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

y aquí está el resultado:

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

Entonces, ¿qué me hace pensar que Random.next() siempre devolvería un nuevo número aleatorio?

¿Fue útil?

Solución

Estás creando el Random casos demasiado cercanos en el tiempo.Cada instancia se inicializa utilizando el reloj del sistema y, como el reloj no ha cambiado, obtienes la misma secuencia de números aleatorios una y otra vez.

Crear una única instancia del Random clase y úsala una y otra vez.

Utilizar el using palabra clave para que el StreamWriter se cierra y se desecha cuando haya terminado con él.El código de un bucle es más fácil de reconocer si utiliza el for palabra clave.

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

El método toma la Random objeto como parámetro.

Además, utilice la longitud para inicializar StringBuilder con la capacidad correcta, de modo que no tenga que reasignarse durante el ciclo.Utilice el operador < en lugar de <= en el bucle; de ​​lo contrario, creará una cadena que tiene un carácter más larga que el length El parámetro especifica.

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

Otros consejos

Consulte Descripción del constructor aleatorio en MSN, esta parte:

  

El valor inicial predeterminado se deriva de   el reloj del sistema y tiene finito   resolución. Como resultado, diferente   Objetos aleatorios que se crean en   estrecha sucesión por una llamada a la   el constructor predeterminado tendrá   valores de semilla predeterminados idénticos y,   por lo tanto, producirá conjuntos idénticos   de números aleatorios.

Entonces, llame al constructor Random () solo una vez al comienzo de su programa o use el constructor Random (int32) y defina una semilla variable usted mismo.

Porque crea un nuevo objeto aleatorio en cada llamada.

Simplemente mueva el randomNumber fuera del método y conviértalo en un miembro de la clase.

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

Todos los generadores aleatorios de software son 'pseudoaleatorios', producen una secuencia de bases numéricas en una semilla (inicial). Con la misma semilla producen la misma secuencia. A veces esto es útil. Si desea producir su programa para producir la misma secuencia en cada ejecución, puede usar new Random(0).

Editar: aparentemente la clase .Net Random se está auto-sembrando, no lo sabía. Por lo tanto, es un problema de tiempo, como lo han señalado otros.

solo declara randomNumber una vez



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

la semilla para los números aleatorios son todos iguales debido a la corta cantidad de tiempo que lleva, de hecho, usted recrea el generador aleatorio con la misma semilla cada vez, por lo que la llamada Next () devuelve el mismo valor aleatorio.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top