2017-09-26 58 views
3

我想學習Elm,並且當前我想創建一個包含索引和隨機數的元組的隨機列表。
我目前的做法是創建一個列表,併爲每個元素創建一個隨機值:爲什麼隨機始終返回一個偶數

randomList = 
    List.map randomEntry (List.range 0 1000) 

randomEntry index = 
    let 
     seed = Random.initialSeed index 
     randomResult = Random.step (Random.int 1 10) seed 
    in 
     (index, Tuple.first randomResult) 

但是,這隻會造成偶數。

爲什麼它總是創建偶數,以及這樣做的正確方法是什麼?

+3

因爲其他數字只是奇數 scrwtp

回答

4

奇怪 - 使用你的randomEntry函數,第一個奇數不會開始顯示,直到53668,然後它是奇數的一段時間。從REPL一個例子:

> List.range 0 100000 |> List.map randomEntry |> List.filter (\(a,b) -> b % 2 /= 0) |> List.take 10 
[(53668,35),(53669,87),(53670,1),(53671,15),(53672,29),(53673,43),(53674,57),(53675,71),(53676,85),(53677,99)] 
    : List (Int, Int) 

現在我不能告訴你爲什麼會出現在這個範圍內(here's the source for the int generator if you're curious)這樣的粘性,但希望我能在榆樹闡明隨機性的一些情況。

真的沒有辦法使用標準計算技術創建一個真正的隨機數發生器(旁邊有量子計算機),所以創建隨機性的典型方法是提供一個函數,它接受一個種子值,返回一個僞隨機數並使用下一個種子值。

這使得隨機數生成可預測,因爲您將始終獲得相同種子的相同「隨機」數。

這就是爲什麼你總是得到相同的輸入結果:你使用的是相同的0到1000的種子值。另外,你忽略了從step函數返回的「next seed」值,它作爲元組的第二個值返回。

現在,在處理隨機數發生器時,儘可能避免處理種子是一個很好的經驗法則。您可以通過構建像intlist等小型發電機來編寫發電機,而無需參照種子。

你執行一個發電機的方式或者是通過返回從update功能從Random.generate產生一個cmd,這讓決定使用哪個種子榆樹架構(這可能使用一些基於時間的種子)的責任,或你可以使用Random.step來傳遞種子,你已經在上面完成了。

所以,回到你原來的例子,如果你寫一個發電機返回一定的規模,每個數字在一定範圍內的隨機數表,它可能是這個樣子:

randomListGenerator : Int -> (Int, Int) -> Random.Generator (List Int) 
randomListGenerator size (low, high) = 
    Random.list size (Random.int low high) 

執行此使用step在REPL顯示它如何使用:

> initialSeed 0 |> step (randomListGenerator 20 (1, 10)) |> Tuple.first 
[6,6,6,1,3,10,4,4,4,9,6,3,5,3,7,8,3,4,8,5] : List Int 

你會看到,這包括一些奇數,不像你最初的例子。它與你的例子不同的事實是因爲生成器返回下一個種子來使用每個連續的步驟,而你的例子按順序使用整數0到1000。我仍然沒有解釋你的原始問題,爲什麼使用你的原始輸入有如此大的平均值,除非說它很奇怪。

+3

從[Random.Pcg for Elm]的文檔引用(http://package.elm-lang.org/packages/mgold/elm-random-pcg/最新/),「如果你使用少於53,668的種子並生成一個布爾值,那麼它將是真的 - 如果你正在使用核心的隨機模塊」 –

相關問題