2012-08-15 44 views
3

我想洗牌的列表的元素相同的結果:System.Random()和Next()返回

(* 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工作正常,我,但我很好奇,爲什麼這種行爲顯示出來)

回答

9

最好由System.Random()'s default constructor手冊解釋;

默認種子值來自系統時鐘,並具有有限的 分辨率。因此,通過調用默認構造函數在 中創建的不同Random對象將具有相同的默認種子值,因此將產生相同的 組隨機數。

3

它,因爲你每次使用相同的種子值以這種方式工作。這就是爲什麼連續調用Random的同一個實例很重要。

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)] 
相關問題