System.Random()。Next()返回相同的结果

时间:2012-08-15 18:41:52

标签: .net f#

我正在试图改变列表中的元素:

(* 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对我来说很好,但我很好奇为什么会出现这种行为。)

3 个答案:

答案 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

实例的原因