Elm Random generator,timestamp as initialSeed

时间:2015-11-22 14:18:50

标签: random elm

我做了一个简单的代码,显示每毫秒Random.bool显示为True或False的时间。发电机以当前时间戳作为种子产生布尔值。

我希望布尔值几乎每次迭代都会改变,但我会得到一个意想不到的大错误。

发生了什么事?

编辑:我使用boolRandom(时间*时间)有更好的结果。

Live preview on share-elm 0.15, with Random.int 0 1

这里有0.16的Random.bool:

import Signal
import Random
import Time exposing (Time)
import Graphics.Element exposing (Element, show, flow, down)

type alias Stat = {time: Time, true: Int, false: Int}

newStat: Stat
newStat = Stat 0 0 0 

scene : Stat -> Element
scene stat = 
  flow down 
    [ "Time: "++(toString stat.time)  |> show
    , "True: "++(toString stat.true)  |> show
    , "False: "++(toString stat.false)  |> show
    ]

boolRandom : Time -> Bool
boolRandom time = 
  Random.generate Random.bool (Random.initialSeed (round time)) |> fst

updateData : Time -> Stat -> Stat
updateData time stat = 
  if boolRandom time == True 
    then {stat | time = time , true = stat.true+1} 
    else {stat | time = time , false = stat.false+1} 

updateEvery : Signal Stat
updateEvery = 
  Signal.foldp updateData newStat (Time.every Time.millisecond)

main = Signal.map scene updateEvery

2 个答案:

答案 0 :(得分:4)

请勿将当前时间用作随机种子,因为您遇到的问题正是如此。你应该在你的程序中只调用Random.initialSeed一次(这意味着一次调用,而不是在一个被称为N次的函数中)。每当您生成一个随机数时,它会为您提供一个新种子,您应该将种子保持在Stat类型而不是时间。然后:

updateData : Time -> Stat -> Stat
updateData time stat = 
  let (bool, seed) = Random.generate Random.bool stat.seed
  in if bool
     then {stat | seed = seed , true = stat.true+1} 
     else {stat | seed = seed , false = stat.false+1}

你也可以删除boolRandom - 丢弃fst的新种子很糟糕!

那么,你如何在第一时间得到一个好的随机种子?当前时间实际上是一个糟糕的选择,因为它不是均匀分布的。相反,在您选择的JS控制台中评估Math.floor(Math.random()*0xFFFFFFFF)并粘贴结果。要获得每次运行变化的程序,请通过端口传递评估该表达式的结果。

答案 1 :(得分:0)

如果人们需要使用静态初始种子的工作解决方案:

import Signal
import Random exposing (Seed)
import Time exposing (Time)
import Graphics.Element exposing (Element, show, flow, down)

type alias Stat = {time: Time, seed: Seed, true: Int, false: Int}

newStat: Stat
newStat = Stat 0 (Random.initialSeed 123456789) 0 0 

scene : Stat -> Element
scene stat = 
  flow down 
    [ "Time: "++(toString stat.time)  |> show
    , "True: "++(toString stat.true)  |> show
    , "False: "++(toString stat.false)  |> show
    ]

updateData : Time -> Stat -> Stat
updateData time stat = 
  let (bool, seed) = Random.generate Random.bool stat.seed
  in if bool
     then {stat | time = time, seed = seed , true = stat.true+1} 
     else {stat | time = time, seed = seed , false = stat.false+1}

updateEvery : Signal Stat
updateEvery = 
  Signal.foldp updateData newStat (Time.every Time.millisecond)

main = Signal.map scene updateEvery