Erlang - Генератор случайных чисел - PullRequest
4 голосов
/ 12 февраля 2011

Я использую следующее для генерации почти случайного числа.

3> erlang:ref_to_list(make_ref()).

"#Ref<0.0.0.36>"

Что я хочу, это 00036

Ну, это было то, что мне сообщили, что я мог сделать в предыдущем посте,Мне пришло в голову, что не так просто извлечь числа из make ref.

Может кто-нибудь показать, как это легко сделать, или, возможно, порекомендовать другое решение.

Имейте в виду, что использованиеrandom: seed () не является случайным при вызове в те же несколько нано секунд.

Regards

1 Ответ

21 голосов
/ 12 февраля 2011

Примечание: из OTP 18 erlang:now/0 и random устарели, а OTP 20 удалит модуль random . См. Коррекция времени и времени в Эрланге для получения дополнительной информации.Кроме того, вам больше не нужно выполнять посев для каждого процесса, если вы используете rand:uniform/0.Следующее оставлено для справки.


Проблема в том, что вы используете random неправильно.random:seed/0 будет всегда заполнять генератор случайных чисел одним и тем же начальным числом.Это не хорошо для того, что вы хотите.Скорее, вы можете использовать random:seed(erlang:now()), чтобы заполнить его другим номером, а именно текущим временем.

"Что произойдет, если два вызова будут очень близки?"Вы можете спросить.Ну, ребята из Erlang подумали об этом, поэтому now/0 гарантированно всегда будет возвращать растущие числа:

Возвращает кортеж {MegaSecs, Secs, MicroSecs}, который истек с 00:00 по Гринвичу1 января 1970 г. (ноль часов) в предположении, что базовая ОС это поддерживает.В противном случае выбирается какой-то другой момент времени. Также гарантируется, что последующие вызовы этого BIF возвращают непрерывно увеличивающиеся значения. Следовательно, возвращаемое значение now () может использоваться для генерации уникальных временных меток, и если оно вызывается в строгом режиме.В цикле на быстрой машине время узла может стать искаженным.

(выделено мое)

Также обратите внимание, что random PRNG является для каждого процесса, поэтому вы должны всегданачните ваш процесс с вызова сеялки:

init([..]) ->
  random:seed(erlang:now()),
  [..]
  {ok, #state { [..] }}.

Использование ссылок для этого возможно возможно, но я не думаю, что это жизнеспособно.Решение выходит за рамки erlang:ref_to_list/1, и это не красиво.

...