Elm Случайный генератор, отметка времени как initialSeed
Я сделал простой код, показывающий, сколько раз Random.bool выглядит как True или False каждую миллисекунду. Генератор генерирует логические значения с текущей меткой времени в качестве начального числа.
Я ожидаю, что булевы значения будут меняться почти каждые итерации, но я получаю неожиданную большую серию True или False.
Что происходит так?
Изменить: у меня есть лучшие результаты с boolRandom (время * время).
Предварительный просмотр на Share-Elm 0,15, с 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 ответа
Не используйте текущее время в качестве случайного начального числа, потому что это именно та проблема, с которой вы столкнулись. Вам следует позвонить 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
плохо!
Итак, как вы получаете хорошее случайное семя в первую очередь? Текущее время на самом деле плохой выбор, поскольку оно не распределено равномерно. Вместо этого оцените Math.floor(Math.random()*0xFFFFFFFF)
в выбранной вами консоли JS и вставьте результат. Чтобы получить программу, которая меняется при каждом запуске, передайте результат оценки этого выражения через порт.
В случае людям нужен рабочий раствор со статическим начальным семенем:
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