我正在试图改变列表中的元素:
(* Returns a list with the same elements as the original but in randomized order *)
let shuffle items =
items
|> List.map (fun x -> (x, System.Random().Next()))
|> List.sortBy snd
|> List.map fst
但是,这总是以相同的顺序返回items
,因为:
> List.map (fun x -> x, System.Random().Next()) [1; 2; 3];;
val it : (int * int) list = [(1, 728974863); (2, 728974863); (3, 728974863)]
> List.map (fun x -> x, System.Random().Next()) [1; 2; 3];;
val it : (int * int) list =
[(1, 1768690982); (2, 1768690982); (3, 1768690982)]
> List.map (fun x -> x, System.Random().Next()) [1; 2; 3];;
val it : (int * int) list = [(1, 262031538); (2, 262031538); (3, 262031538)]
为什么System.Random().Next()
总是在每次通话中返回相同的值?是因为连续的电话按时间顺序太靠近了吗?或者我是否以其他方式误导了API?
(注意:这个answer对我来说很好,但我很好奇为什么会出现这种行为。)
答案 0 :(得分:9)
最好用System.Random()'s default constructor;
手册解释默认种子值是从系统时钟派生的,并且是有限的 解析度。结果,创建了不同的Random对象 通过调用默认构造函数来关闭连续 相同的默认种子值,因此,将产生相同的 随机数集。
答案 1 :(得分:4)
要记住的一件事是,您不是从随机数生成器生成一系列数字,而是创建一系列随机数生成器并生成每个生成器的第一个随机数。
请记住,System.Random().Next()
是(new System.Random()).Next()
的简写,因此您使用Random的默认构造函数在每次迭代时创建一个新的System.Random对象。正如在其他答案中所提到的那样,默认构造函数使用当前时间的粗略值作为RNG的初始种子,因此当快速连续调用时,每次都会重新创建相同的RNG(这将在其上生成相同的数字)第一次也是唯一一次调用。)
解决方案是只创建一个System.Random对象并重用它:
> let rng = new System.Random() in List.map (fun x -> x, rng.Next()) [1; 2; 3];;
val it : (int * int) list = [(1, 483259737); (2, 719806274); (3, 1951956175)]
答案 2 :(得分:3)
它以这种方式工作,因为您每次都使用相同的种子值。这就是为什么连续调用同一个Random
。