[erlang-questions] Random behaviour

John Hughes john.hughes@REDACTED
Mon Sep 6 07:26:25 CEST 2010


Hi Tom,

Every Erlang process has its own random number seed, and it's initialised to a CONSTANT value when the process starts! Hence given

foo() ->
    io:format("~p\n",[[random:uniform(10) || _ <- lists:seq(1,10)]]).

then you get different values from multiple calls in the SAME process:

2> foo:foo().
[1,5,8,10,6,4,6,10,7,5]
ok
3> foo:foo().
[6,2,3,7,2,6,3,5,5,1]
ok
4> foo:foo().
[6,5,5,4,1,6,10,4,2,3]
ok

but the same value every time in a NEW process:

5> spawn(foo,foo,[]).
[1,5,8,10,6,4,6,10,7,5]
<0.45.0>
6> spawn(foo,foo,[]).
[1,5,8,10,6,4,6,10,7,5]
<0.47.0>
7> spawn(foo,foo,[]).
[1,5,8,10,6,4,6,10,7,5]
<0.49.0>

I guess it makes sense--you don't want to pay the price of initialising a random number seed every time you start a process--but it is a bit of a gotcha.

If you want different random numbers in different processes (which you usually do), then you need to initialise the seed differently when you start the process. The usual trick is to use now(), since a seed just happens to be three integers:

baz() ->
    {A,B,C} = now(),
    random:seed(A,B,C),
    foo().

and now

10> spawn(foo,baz,[]).
[10,7,9,4,7,1,4,8,3,6]
<0.61.0>
11> spawn(foo,baz,[]).
[10,5,1,6,5,5,9,3,6,2]
<0.63.0>
12> spawn(foo,baz,[]).
[8,7,9,7,9,6,1,9,4,3]
<0.65.0>

One thing to be aware of is that calls to now() close together in time give you seeds the initially generate similar numbers:

13> spawn(foo,baz,[]),spawn(foo,baz,[]).
[10,1,8,1,8,1,8,10,1,9]
[10,1,7,1,6,5,7,8,8,2]
<0.68.0>
14> spawn(foo,baz,[]),spawn(foo,baz,[]).
[5,9,8,2,2,3,3,9,5,8]
[5,9,7,2,9,6,2,7,2,1]
<0.71.0>
15> spawn(foo,baz,[]),spawn(foo,baz,[]).
[10,5,2,3,4,4,3,1,6,3]
[10,5,1,4,2,8,3,9,3,7]
<0.74.0>

Note the first two numbers generated are always the same in both processes, even though they start with different seeds. If you're going to start many processes and you want to be sure they have independent random numbers then you have to be a bit more careful how you initialise the seed--but if there are going to be seconds or more between each process start then you don't have to worry.

John
  ----- Original Message ----- 
  From: tom kelly 
  To: erlang-questions@REDACTED 
  Sent: Sunday, September 05, 2010 8:45 PM
  Subject: [erlang-questions] Random behaviour


  Hello List,


  I just found a bahaviour I didn't expect in OTPs random module, it's not necessarily a bug but I thought I'd share it here all the same.


  I wrote a simple random data generator using random:uniform() to help me track a bug that was triggered by certain input data that I couldn't catch. The minimal example is attached in demo.erl.


  If you run the test function it will probably pass a few times but will eventually hit my "bug" and fail. Whenever the bug is triggered the test function gets a badmatch and the current process dies. The behaviour I wasn't expecting now occurs, everytime I repeat the test function I get the exact same sequence of numbers from random:uniform.


  I can call random:uniform from the shell to move it on one step in the sequence and probably pass another test, but when it fails again my process dies and again I repeatedly get a repeated sequence of numbers. The sequence from this second fail is different from the first fail so it hasn't just gone back to the start.


  I don't expect to be saved from my own bugs but just thought this was a strange behaviour from random. If anyone is using random in their application they should be aware of this.


  //Tom.




  8> demo:test_my_buggy_code().
  ok - [15,21,70,16,56,22,46,43,1,57]
  ok
  9> demo:test_my_buggy_code().
  ok - [41,31,6,58,99,34,19,21,4,89]
  ok
  10> demo:test_my_buggy_code().
  ok - [83,33,26,81,2,3,5,6,99,57]
  ok
  11> demo:test_my_buggy_code().
  ** exception error: no match of right hand side value [1,39,67,88,90,80,59,30,
                                                         72,41,80]
       in function  demo:test_my_buggy_code/0
       in call from random:uniform/0
  12> demo:test_my_buggy_code().
  ** exception error: no match of right hand side value [1,39,67,88,90,80,59,30,
                                                         72,41,80]
       in function  demo:test_my_buggy_code/0
       in call from random:uniform/0
  13> random:uniform(1).        
  1
  14> demo:test_my_buggy_code().
  ok - [67,88,90,80,59,30,72,41,80,8]
  ok
  15> demo:test_my_buggy_code().
  ok - [60,68,65,8,27,61,1,94,82,65]
  ok
  16> demo:test_my_buggy_code().
  ok - [47,2,62,94,25,97,94,87,27,32]
  ok
  17> demo:test_my_buggy_code().
  ok - [59,21,10,14,17,24,93,78,34,28]
  ok
  18> demo:test_my_buggy_code().
  ** exception error: no match of right hand side value [1,3,59,96,93,32,99,34,
                                                         60,42,2]
       in function  demo:test_my_buggy_code/0
       in call from random:uniform/0
  19> demo:test_my_buggy_code().
  ** exception error: no match of right hand side value [1,3,59,96,93,32,99,34,
                                                         60,42,2]
       in function  demo:test_my_buggy_code/0
       in call from random:uniform/0
  20> demo:test_my_buggy_code().
  ** exception error: no match of right hand side value [1,3,59,96,93,32,99,34,
                                                         60,42,2]
       in function  demo:test_my_buggy_code/0
       in call from random:uniform/0
  21> 




------------------------------------------------------------------------------



  ________________________________________________________________
  erlang-questions (at) erlang.org mailing list.
  See http://www.erlang.org/faq.html
  To unsubscribe; mailto:erlang-questions-unsubscribe@REDACTED


More information about the erlang-questions mailing list