Erlang Central

Difference between revisions of "Random Numbers"

From ErlangCentral Wiki

 
Line 77: Line 77:
 
It can support bigint values, so no special recipe is required for extremely large random numbers.  
 
It can support bigint values, so no special recipe is required for extremely large random numbers.  
  
[[Category:CookBook]]
+
[[Category:CookBook]][[Category:NumberRecipes]]

Revision as of 23:10, 3 September 2006

Problem

You want a random number from a given range. For example, you wish to randomly select one element from an array, simulate rolling a die in a game of chance, or generate a random password.

Solution

Use random:uniform function from the standard Erlang distribution. It has two forms: (1) a no-argument version that returns a random float value in the range of 0.0 to 1.0, and (2) an version that takes a single integer (N) and returns a random integer in the range of 1 to N.

1> random:uniform().
9.23009e-2
2> random:uniform(150).
67

This code generates and prints a random integer between 25 and 75, inclusive:

3> io:fwrite("Random = ~B\n", [random:uniform(51) + 24]).
Random = 74
ok

In the example, we want to limit the range to 25 to 75, so we add 24 to the result of the random:uniform function. This means we really want a random number between 1 and 51, so we give the random:uniform function the argument 51 (since the generated number is always from 1 to N).

The canonical application for this kind of number generation is the random selection of an element from a vector:

4> Dict = dict:from_list([{1,$a}, {2,$b}, {3,$c}, {4,$d}, {5,$1},
4>   {6,$2}, {7,$3}]).                                             
{dict,7,
      16,
      16,
      8,
      80,
      48,
      {[],[],[],[],[],[],[],[],[],[],[],[],[],[],[],[]},
      {{[],
        [[3|99]],
        [[6|50]],
        [],
        [],
        [],
        [[2|98]],
        [[5|49]],
        [],
        [],
        [],
        [[1|97]],
        [[4|100]],
        [[7|51]],
        [],
        []}}}
5> dict:fetch(random:uniform(7), Dict).
100
6> io:fwrite("~c\n", [100]).
d
ok

Another common example is generating a random password:

generate_8_password() ->
    lists:flatten(lists:foldl(fun(X,AccIn) ->
        [random:uniform(90) + 32|AccIn] end,
        [], lists:seq(1,8))).

7> generate_8_password().
"]VD'hEa;"
8> generate_8_password().
"Zju!W9'Z"
9> generate_8_password().
"uw6uX\"JF"
10> generate_8_password().
"-)3Ue=8n"

The Erlang random number generator is attributed to B.A. Wichmann and I.D.Hill, in 'An efficient and portable pseudo-random number generator', Journal of Applied Statistics. AS183. 1982. Also Byte March 1987.

It can support bigint values, so no special recipe is required for extremely large random numbers.