[erlang-questions] Random behaviour

tom kelly ttom.kelly@REDACTED
Mon Sep 6 10:08:49 CEST 2010


Hi John,
Thanks for the comprehensive explanation!
//Tom.


On Mon, Sep 6, 2010 at 6:26 AM, John Hughes <john.hughes@REDACTED> wrote:

>  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 <ttom.kelly@REDACTED>
> *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