Elm 随机生成器,时间戳为 initialSeed
Elm Random generator, timestamp as initialSeed
我编写了一个简单的代码来显示 Random.bool 每毫秒出现多少时间为 True 或 False。生成器生成以当前时间戳为种子的布尔值。
我希望布尔值几乎每次迭代都会改变,但我得到了意想不到的大量 True 或 False。
这是怎么回事?
编辑:我用 boolRandom (time*time) 得到了更好的结果。
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
不要使用当前时间作为随机种子,因为正是您遇到的问题。您应该在您的程序中恰好调用一次 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)
并粘贴结果。要获得每个 运行 都不同的程序,请通过端口传递对该表达式求值的结果。
如果人们需要一个带有静态初始种子的工作解决方案:
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
我编写了一个简单的代码来显示 Random.bool 每毫秒出现多少时间为 True 或 False。生成器生成以当前时间戳为种子的布尔值。
我希望布尔值几乎每次迭代都会改变,但我得到了意想不到的大量 True 或 False。
这是怎么回事?
编辑:我用 boolRandom (time*time) 得到了更好的结果。
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
不要使用当前时间作为随机种子,因为正是您遇到的问题。您应该在您的程序中恰好调用一次 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)
并粘贴结果。要获得每个 运行 都不同的程序,请通过端口传递对该表达式求值的结果。
如果人们需要一个带有静态初始种子的工作解决方案:
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