使用System.Random()获取随机数列表的F#给出了相同的列表

时间:2016-07-26 12:49:25

标签: random f# f#-interactive mathdotnet

我一直在搜索其他问题,用户会在循环或方法中实例化许多System.Random(),因此会从同一时钟创建许多相同的random。但是在这里我有一个实例化的System.Random()但是当我尝试使用它创建多个随机数列表时,它们都是相同的。

module Scripts =
let rnd = System.Random() 

let getRandom36 =
    let rec generate (l : list<int>) =
        match l.Length with
        |8 -> l
        |_ -> let number = rnd.Next 38
              if(List.exists(fun elem -> elem=number) l) then generate l else generate (number::l)
    List.sort(generate List.empty)

let myseq = Seq.init 4 (fun _ -> getRandom36)

重要的部分并不是getRandom36中的代码是如何工作的,我一直在篡改它以不同的方式工作,但是在调用myseq;;时我一直看到相同的列表。< / p>

myseq;;
val it : seq<int list> =
  seq
    [[2; 8; 10; 11; 18; 21; 22; 35]; [2; 8; 10; 11; 18; 21; 22; 35];
     [2; 8; 10; 11; 18; 21; 22; 35]; [2; 8; 10; 11; 18; 21; 22; 35]; ...]

任何想法为什么?我的意思是每次rnd.Next不应该不同,因为每次迭代都没有新的rnd实例。

3 个答案:

答案 0 :(得分:5)

getRandom36是一个不是函数的值。可以修改如下:

let rnd = System.Random() 

let getRandom36 _ =
    let rec generate (l : list<int>) =
        match l.Length with
        |8 -> l
        |_ -> let number = rnd.Next 38
              if(List.exists(fun elem -> elem=number) l) then generate l else generate (number::l)
    List.sort(generate List.empty)

let myseq = Seq.init 4 getRandom36

答案 1 :(得分:2)

问题是getRandom36是一个值,而不是一个函数。它被评估一次,然后总是返回相同的列表。把它变成一个函数,它应该可以正常工作:

module Scripts =

    let rnd = System.Random ()

    let getRandom36 () =
        let rec generate (l : _ list) =
            match l.Length with
            | 8 -> l
            | _ -> let number = rnd.Next 38
                   if List.exists (fun elem -> elem = number) l
                   then l else (number :: l)
                   |> generate
        List.sort (generate [])

    let myseq = Seq.init 4 (fun _ -> getRandom36 ())

答案 2 :(得分:0)

虽然OP可能正在寻找使用递归的非常具体的解决方案,但使用MathDotNet甚至股票System.Random可以更轻松/更快捷地生成随机数。

例如:

#load @"..\..\FSLAB\packages\FsLab\FsLab.fsx"

open MathNet.Numerics.LinearAlgebra
open MathNet.Numerics.Distributions
open MathNet.Numerics.Random

let rng = Random.shared
Array2D.init<int> 4 8 (fun i j -> rng.Next(38)) 

或者:

[for i in 1..4 -> List.init 8 (fun x -> rnd.Next(38))]

还有像.NextInt32s这样的函数可以填充已经存在的数组,例如:

let fillArray (x:int []) = rng.NextInt32s(x,0,38)
let xs = [|for i in 1..4 -> Array.zeroCreate<int> 8|]
xs |> Array.map (fun x -> fillArray(x))