2011-01-31 8 views
10

posibles duplicados:
c# - getting the same random number repeatedly
Random number generator not working the way I had planned (C#)generación de números aleatorios - Mismo número devuelto

Tengo un método que se basa una cola de enteros:

public Queue<int> generateTrainingInts(int count = 60) 
    { 
     Queue<int> retval = new Queue<int>(); 

     for (int i = 0; i < count; i++) 
     { 
      retval.Enqueue(JE_Rand.rInt(2001, 100)); 
     } 

     return retval; 
    } 

JE_Rand .rInt() es solo una función que delegat es una función de la clase Random:

public static int rInt(int exclUB, int incLB = 0) 
    { 
     Random rand = new Random(DateTime.Now.Millisecond); 
     int t = rand.Next(incLB, exclUB); 
     rand = null;    
     return t; 
    } 

Pero cuando llamo generateTrainingInts, el mismo número está en cola cada vez. Sin embargo, si cambio rInt para usar una instancia estática de la clase Random, en lugar de una instancia local (con el alcance de la función como se definió anteriormente), parece que funciona correctamente (encola los enteros aleatorios). ¿Sabe alguien por que ha ocurrido esto?

Edit: Estimados que respondieron que no leyeron completamente mi pregunta, Como algunos de ustedes señalaron, estoy buscando una buena explicación de por qué sucede esto. No busco una solución al problema generado por el mismo número, porque ya lo arreglé como dije antes. Sin embargo, gracias por su entusiasmo :) Realmente solo quiero entender cosas como esta, porque mi primera implementación tuvo más sentido conceptual para mí.

+0

Parece duplicado ... Mira preguntas realted como -http: //stackoverflow.com/questions/1437825/random-number-generation-in-c –

+0

Esto sucede porque el objeto 'Random' se inicia a partir 'Medio ambiente.GetTickCount', que es un temporizador de milisegundos. Entonces, si llamas al constructor 'Random' dos veces en el mismo milisegundo, obtendrás el mismo valor inicial. –

+0

Cuando Rand se crea una instancia con la misma semilla (por ejemplo, DateTime.Now.Millisecond en su caso), devolverá las mismas secuencias de valores. Debe crear una instancia una vez (y almacenarlo en una variable estática), o con diferentes semillas en cada momento. – AFract

Respuesta

23

Debe conservar el mismo objeto Random. Ponerlo fuera de su método estático como un miembro estático

private static Random rand = new Random(); 

public static int rInt(int exclUB, int incLB = 0) 
{ 
    int t = rand.Next(incLB, exclUB); 
    return t; 
} 

Editar
La razón es la resolución finita del reloj utiliza para inicializar Random. Las inicializaciones posteriores de Random obtendrán la misma posición inicial en la secuencia aleatoria. Al reutilizar el mismo Random, el siguiente valor en la secuencia aleatoria siempre se genera.

+0

El OP ya lo intentó y estaba preguntando * por qué *. –

+0

¿Por qué asignar rand a null después de la generación? Como Rand's será instanciado en un rango de tiempo muy corto, las dos instancias obtendrán la misma semilla y devolverán el mismo valor, exactamente como en la versión del autor. Deberías ponerlo estático y mantener siempre la misma instancia. También es posible usar múltiples instancias con diferentes semillas, por ejemplo usando un "Guid.NewGuid(). GetHashCode()" como semilla, pero obtendrás actuaciones terribles. – AFract

+0

Veo que ha corregido su muestra de código. Era boggus, pero debería funcionar ahora ... – AFract

5

probar el siguiente código y creo que verá por qué:

void PrintNowAHundredTimes() 
{ 
    for (int i = 0; i < 100; ++i) 
    { 
     Console.WriteLine(DateTime.Now); 
    } 
} 

Los Random objetos están recibiendo la misma semilla y otra vez. Esto se debe a que la granularidad del tiempo del sistema devuelto por DateTime.Now es, simplemente, finito. En mi máquina, por ejemplo, el valor solo cambia cada ~ 15 ms. Así que las llamadas consecutivas dentro de ese período de tiempo regresan al mismo tiempo.

Y como sospecho que ya sabe, dos objetos Random inicializados con el mismo valor inicial generarán secuencias aleatorias idénticas. (Es por eso que se llama pseudoaleatoria, técnicamente.)

También debe tener en cuenta que incluso si tuviera sentido para crear instancias de un nuevo Random objeto localmente dentro de su método, estableciéndolo en null que todavía no sirven para nada (una vez que el El método sale no habrá más referencias al objeto de todos modos, por lo que será basura recogida independientemente).

1
public class JE_Rand 
{ 
    private static Random rand= new Random(DateTime.Now.Millisecond); 

    public static int rInt(int exclUB, int incLB = 0) 
    { 
     int t = rand.Next(incLB, exclUB); 
     return t; 
    } 
} 
+0

¿por qué rand = null? va a volcar el objeto, y la próxima llamada lanzará una excepción – walter

+0

@walter: Esta es una respuesta antigua, pero solo estaba copiando y pegando su código y moviendo el nuevo Random (...) fuera de la llamada al método. Aunque eres 100% correcto. Editaré mi respuesta. – BFree

Cuestiones relacionadas