2017-02-20 4 views
1

Как разбить генератор случайных чисел SML/NJ на машину Windows?Сеяние RNG SML/NJ на машине Windows

Функция Random.rand() берет пару целых чисел и использует их для засева генератора случайных чисел. Основываясь на моем опыте работы с другими языками программирования, я бы ожидал, что будет относительно простой способ засеять его на основе системных часов (что-то вроде srand(time(null)); в C). Если я не упускаю из виду что-то очевидное, похоже, что нет простого способа, по крайней мере, если вы используете Windows.

Ближайший Я могу найти time(null) в SML is Posix.ProcEnv.time, который возвращает эпоху эпохи Unix. К сожалению, структуры Posix не являются частью загрузки Windows, а структура Windows (которая есть), похоже, не содержит прямого аналога time.

Структура Timer имеет способы определения истек в реальном времени. Я мог бы написать функцию, которая составляет около полусекунды бессмысленного вычисления, время, необходимое для этого, и выяснить способ извлечь из него пару целых чисел. Но: 1) это очень много работы для чего-то, что тривиально в большинстве языков, 2) что более важно - похоже, это может привести к повторному использованию одного и того же семени в нетривиальном проценте времени.

Еще одна идея, которую я имел, это то, что если бы я мог получить доступ к переменной среды Windows "TIME", я мог бы ее использовать. Следующее отпечатывает время на замену:

OS.Process.system "TIME/T"; 

но не предоставляет программный доступ к печатной строке.

OS.Process.getEnv "TIME"; 

звучит многообещающе, но возвращает NONE.

Если в SML/NJ действительно нет простого решения - существуют ли опции, которые работают для некоторых других реализаций SML, таких как Poly/ML?

ответ

3

Подпись функции TIME Базы библиотеки имеет функцию для возврата текущего времени.

val now: unit -> t 
+0

Это должно сработать. Странно думать, что я взглянул на «Время» более одного раза, но не заметил этого. У меня создалось впечатление, что «Время» было разработано для синтаксического анализа значений, возвращаемых с «Таймера», но в этом не было данных о часах. –

+0

Я пропустил это тоже в обычной документации, обновит ответ, чтобы отразить его стандартную функцию – matt

2

@matt ответил на вопрос сам по себе, как получить системные часы, читаемые портативным способом. В дополнение к его ответу, вот семенная функция. В качестве технической проблемы количество прошедших секунд с 1970 года слишком велико для 31-битного int SML/NJ. Я мог бы использовать большие возможности, но простое решение, казалось, должно было просто уменьшить на 1,48 миллиарда до преобразования в int (и использовать десятичную часть времени для получения второго параметра семенного ввода):

fun seed() = 
    let 
     val r = Time.toReal(Time.now()) - 1.48e9 
     val f = Real.realFloor(r) 
     val d = r - f 
     val i = Real.floor(f) 
     val j = Real.floor(1000.0*d) 
    in 
     Random.rand(i,j) 
    end; 

Существует почти определенно более принципиальный способ сделать это, но вышеупомянутые работы:

- val s = seed(); 
val s = 
    RND 
    {borrow=ref false,congx=ref 0wx4B7CD4CA,index=ref 0, 
    vals=[|0wx40E9888B,0wx6F1B97FD,0wx4011C479,0wx2012F528,0wx3CDC0237, 
      0wx7C36E91D,0wx5361B64D,0wx4B61A297,0wx61823821,0wx7C6CD6BD, 
      0wx1683CA4D,0wx670A75AF,...|]} : Random.rand 
- Random.randRange(1,100) s; 
val it = 35 : int 
- val s = seed(); 
val s = 
    RND 
    {borrow=ref false,congx=ref 0wx512EBCFC,index=ref 0, 
    vals=[|0wx456E115A,0wx27817499,0wx46A6BE48,0wx2C79BB3,0wx3FF47B4D, 
      0wx5B48FC93,0wx53C3647F,0wx32E40F5A,0wx157AB4C8,0wx16E750D, 
      0wx78BD3EA3,0wx7885CA23,...|]} : Random.rand 
- Random.randRange(1,100) s; 
val it = 73 : int 

не очень интересно, но последовательная рассада sepearated всего на несколько секунд, полученных различные результаты, как и ожидалась.

Смежные вопросы