简体   繁体   中英

F# getting a list of random numbers

I am trying to fill a list with random numbers and am having diffculty getting the random number part. What I have right now prints out a random number 10 times, what I want is to print out 10 different random numbers

   let a = (new System.Random()).Next(1, 1000)


   let listOfSquares = [ for i in 1 .. 10->a]
    printfn "%A" listOfSquares

any tips or suggestions?

Your code is simply getting one random number and using it ten times.

This extension method might be useful:

type System.Random with
    /// Generates an infinite sequence of random numbers within the given range.
    member this.GetValues(minValue, maxValue) =
        Seq.initInfinite (fun _ -> this.Next(minValue, maxValue))

Then you can use it like this:

let r = System.Random()
let nums = r.GetValues(1, 1000) |> Seq.take 10
let genRandomNumbers count =
    let rnd = System.Random()
    List.init count (fun _ -> rnd.Next ())

let l = genRandomNumbers 10
printfn "%A" l

When I write a random something dispenser I like to use the same random number generator for each call to the dispenser. You can do that in F# with closures (a combination of Joel's and ildjarn's answer).

Example:

let randomWord =
    let R = System.Random()
    fun n -> System.String [|for _ in 1..n -> R.Next(26) + 97 |> char|]

In this way, a single instance of Random is 'baked into' the function, reusing it with each call.

There are two problems:

1) In F# functions are supposed to be pure so a function without arguments is considered as final value.

To declare impure function "without arguments", let it take one argument of type unit

let a () = (new System.Random()).Next(1, 1000)

and call it passing unit argument

let list = [ for i in 1 .. 10 -> a () ]

Source

2) New System.Random() instance is created each time when a is called. This results in getting same numbers. To fix this, create the instance only once

let random = new System.Random()
let a () = random.Next(1, 1000)
let list = [ for i in 1 .. 10 -> a ()]

This isn't specific to F#, read explanation for C# for better understanding

You could also avoid declaring an impure function as said by Pavel and just run:

let rnd = Random()
let rndList = [for i in 0..100 do rnd.Next(1000)]

I think one should be careful how to initialize System.Random as it uses the current time as seed. One instance should be enough for the whole app. Injecting random into functions has the advantage that you can use a fixed seed and reproduce with semi randomness, eg for testing your logic.

let rnd = System.Random()
let genRandomNumbers random count =
    List.init count (fun _ -> random.Next ())
let getRandomNumbersSeeded = getRandomNumbers rnd

let l = getRandomNumbersSeeded 10
printfn "%A" l

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM