Erlang - 随机数生成器

4
我正在使用以下代码生成接近随机的数字。
3> erlang:ref_to_list(make_ref()).

"#Ref<0.0.0.36>"

我想要的是00036。
之前有人告诉我可以从make ref中提取数字,但实际操作起来并不容易。是否有人能够简单地展示如何提取数字,或者推荐另一种解决方案。
请注意,在同几个纳秒内调用random:seed()时,它不是随机的。
谢谢。

2
不要在每次调用时重新播种你的随机数生成器。只需播种一次,然后使用它。random模块非常适合此用途。 - nmichaels
你能澄清一下你想要随机数还是唯一数吗?它们是非常不同的实体,而“make_ref”绝对不会产生随机数。 - archaelus
是的,还要说明你想要用随机数来做什么,是游戏、模拟还是安全方面的。因为对于安全性而言,你需要完全不同的随机数。 - Peer Stritzinger
1个回答

22

注意:从OTP 18开始 erlang:now/0 random 模块已弃用,OTP 20将删除 random 模块。 有关详细信息,请参见Erlang中的时间和时间纠正。如果使用rand:uniform/0,则您不再需要执行每个进程的种子设置。以下内容仅供参考。


问题在于,您正在错误地使用randomrandom:seed/0 将始终使用完全相同的种子来生成随机数。这对你想要的结果不好。 相反,可以使用random:seed(erlang:now()) 使用另一个数字-即当前时间-来种植它。

“如果两个调用非常接近会发生什么?” 您可能会问。 好吧,Erlang的开发人员已经考虑到了这一点,因此可以保证now/0 始终返回递增的数字:

返回元组 {MegaSecs,Secs,MicroSecs},它是从1970年1月1日00:00 GMT(零时)以来经过的时间,假设底层操作系统支持此功能。 否则,将选择其他某个时间点。还保证随后对此BIF的调用返回连续递增的值。 因此,从now()的返回值可以用于生成唯一的时间戳,如果在快速计算机上紧密循环调用它,则节点的时间可能会发生变化。

(强调我的)

还请注意,random PRNG是每个进程的,因此您应始终使用种子设置调用启动进程:

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

也许使用引用来解决这个问题是可能的,但我认为这不是一个可行的方案。该解决方法需要使用erlang:ref_to_list/1函数,而且不够简洁。


1
你还没有说明你想要一个唯一的值(没有其他人有这个值)还是随机的值(没有人可以轻易地猜到这个值)。此外,你也没有说明需要多大程度的随机性。你可能需要详细阐述这些内容 - 否则别人无法帮助你。 - I GIVE CRAP ANSWERS
2
+1 对于“PRNG是每个进程独立的”非常赞同。这正是我在寻找的信息。 - Dacav
1
为了获得更随机和安全的种子,您应该使用 crypto:strong_rand_bytes/1 - Berzemus
@jj1bdx,OTP 18+中不需要使用任何种子吗? - quantumpotato
您不必在Erlang rand模块上显式执行种子初始化操作。请参阅https://github.com/erlang/otp/blob/maint-25/lib/stdlib/src/rand.erl#L280-L283,了解OTP 25上rand模块的默认种子初始化方式。 - jj1bdx
显示剩余2条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接