Home > English, Erlang > How to generate random numbers in Erlang

How to generate random numbers in Erlang


For one of my Erlang side projects, I needed to generate a random number. This is a quite common problem in software development, especially if you are implementing some kind of game (e.g., shuffling a deck of cards, rolling a pair of dice).  

Erlang provides for this kind of needs the module random, which allows pseudo-random number generation using Wichmann and Hill’s method (if you are interested you can find it in their publication: “An efficient and portable pseudo-random number generator“). In practive, every time a random number is requested, a state is used to calculate it, and the state is updated. The aforesaid state can be kept in the process dictionary or can be an explicit argument and return value.

Too much talking, gimme my random number!

Ok, to generate a random number you can just use random:uniform/0 and random:uniform/1; in the first case the value returned will be a random float number uniformly distributed between [0.0,1.10 (Gosh, this reminds me of the statistics classes I have taken in these years!) , while in the second case you will obtain a random integer uniformly distributed between [1,N], where obviously N>=1 is an integer used as  parameter by the function.

Let’s try this!

paolo@ubuntu:~/Scrivania$ erl
Eshell V5.9 (abort with ^G)
1> random:uniform().
0.4435846174457203
2> random:uniform(4).
3

Great! We are heroes! We can code our killer Texas Holdem Application!

Not so fast guys! What happens if we exit this shell and open another?

paolo@ubuntu:~/Scrivania$ erl
Eshell V5.9 (abort with ^G)
1> random:uniform().
0.4435846174457203
2> random:uniform(4).
3

No way! We get the same result…this is really strange…but is it? Well, in fact before calling random:uniform/0 or random:uniform/1 we should perform a seeding. The module random gives you a nice function for this wich is, guess what?, random:seed/0 or random:seed/1. A good parameter for the seeding operation could be the one obtained by the bif now(), which is guaranteed to give unique numbers for different calls.

Let’s try it!

1> random:seed(now()).
{8236,26623,17360}
2> {A, B, C} = now().
{1329,311552,420522}
3> random:seed(A,B,C).
{1330,8476,19723}

Kill the shell and try again, you should obtain different values! Ok, is it all Paolo? Well, I would like to say that somebody much more competent, pointed out that the value obtained from BIF now() is kind of bad seed value for the random algorithm used in Erlang. The suggestion is to use crypto:rand_bytes(12) in order to generate 12 crypto-safe random bytes. At this point doing <<A:32, B:32, C:32>> we cast the 12 bytes to 3 integers to be passed as arguments to the seeding function. The drawback here is that you code will be slightly slower.

I have seen also other implementation of this which don’t take into account the module random. Somebody ad example uses erlang:make_ref/0 in combo with erlang:ref_to_list/1 and parsing. This is mostly due to the fact that make_ref/0 returns an almost unique reference (according to official documentation the returned reference will re-occur after approximately 2^82 calls; therefore it is unique enough for practical purposes). Anyhow refs aore  unique only for one launch of one VM, therefore  they are repeatable and predictable.

Last things! I suggest you to try all the examples with two connected node to see how all this implementation works (e.g. are refs and random:uniform without seeding uniques among nodes?), moreover I suggest you to take a look at http://www.trapexit.org/Random_Numbers, you will find a nice tutorial to generate random passwords there…do you think you can improve that code?

About these ads
Categories: English, Erlang Tags: , , ,
  1. No comments yet.
  1. No trackbacks yet.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

Follow

Get every new post delivered to your Inbox.

Join 26 other followers

%d bloggers like this: