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
Другие вопросы по тегам