2011-09-18 10 views
5

Estoy intentando desarrollar un "generador" de números aleatorios en F #.Forzar múltiples evaluaciones de una función en F #

que ha creado correctamente la siguiente función:

let draw() = 
    let rand = new Random() 
    rand.Next(0,36) 

Esto funciona bien y genera un número entre 0 y 36.

Sin embargo, yo estoy tratando de crear una función que se ejecuta esta función varias veces .

He intentado lo siguiente

let multipleDraws (n:int) = 
    [for i in 1..n -> draw()] 

Sin embargo, solo me dan un resultado único, como draw se evalúa sólo una vez en el de la comprensión.

¿Cómo podría forzar múltiples ejecuciones de la función draw?

Respuesta

8

El problema es con el tipo aleatorio. Utiliza el tiempo de la computadora para generar una semilla y luego genera los números aleatorios. Como prácticamente el tiempo de las llamadas es idéntico, se genera la misma semilla y también se devuelven los mismos números.

Esto va a resolver su problema:

let draw = 
    let rand = new Random() 
    fun() -> 
    rand.Next(0,36) 

Y luego:

let multipleDraws (n:int) = 
    [for i in 1..n -> draw()] 
+0

Ok gracias, pero no entiendo, usando su solución, ¿por qué todavía no tengo el mismo problema con la semilla? – SRKX

+0

Cuando llamas al constructor de Random, generas una semilla basada en la hora actual de la computadora. Luego, cada llamada al método Next genera un nuevo seed * basado en el seed * anterior, y no en función del tiempo.Como ya no depende del tiempo, no importa que sus llamadas se realicen en la misma hora de la máquina. –

+2

@SRKK: Es posible que desee agregar 'printfn 'draw que se llama' 'como una primera línea del cuerpo' draw' para ver lo que está sucediendo: verá solo una salida. Su función 'dibujar' devuelve enteros, mientras que uno en la respuesta devuelve una función anónima con la firma' (unidad -> int) 'que en realidad se llama dentro de la lista de comprensión. Esta función anónima captura el valor 'rand' en un cierre,' rand' se sembró solo una vez. –

6

La adición de este para ayudar a explicar la respuesta de Ramón.

Este código utiliza una función lambda.

let draw = 
    let rand = new Random() 
    fun() -> 
    rand.Next(0,36) 

Puede ser más fácil entender lo que sucede si le da un nombre a la función lambda.

let draw = 
    let rand = new Random() 
    let next() = 
     rand.Next(0,36) 
    next 

Al dibujo de la variable se le asigna la siguiente función. Puede mover el rand y el siguiente fuera del alcance del sorteo para ver la asignación directamente.

let rand = new Random() 
let next() = 
    rand.Next(0,36) 
let draw = next 

Se puede ver en el código anterior que en la respuesta de Ramón nueva aleatoria sólo se le llama una vez tanto que se dice muchas veces en el ejemplo de SRKX.

Como lo menciona Ramon Random genera una secuencia de números basada en una semilla aleatoria. Siempre generará la misma secuencia de números si usa la misma semilla. Puede pasar al azar una semilla como esta new Random(2). Si no le pasa un valor, usa la hora actual. Por lo tanto, si llama a un nuevo Random varias veces seguidas sin una semilla, lo más probable es que tenga la misma semilla (porque el tiempo no ha cambiado). Si la semilla no cambia, el primer número aleatorio de la secuencia siempre será el mismo. Si prueba el código original de SRKX y llama a múltiplesDraws con un número lo suficientemente grande, entonces el tiempo cambiará durante el ciclo y obtendrá una secuencia de números que cambia cada cierto tiempo.

+0

¡Gracias por la explicación adicional! lo hace aún más claro. – SRKX

Cuestiones relacionadas