Random Numbers

From Erlang Community

(Difference between revisions)
Revision as of 23:10, 3 September 2006 (edit)
Bfulgham (Talk | contribs)

← Previous diff
Revision as of 10:32, 25 September 2006 (edit) (undo)
Ayrnieu (Talk | contribs)
(they aren't different 'forms' of 'random:uniform', they are two separate functions ; use cleaner password example; remove annoying dict example; minor cleanps)
Next diff →
Line 5: Line 5:
== Solution == == 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. +Use random:uniform/0 and random:uniform/1 ; the first returns a random float uniformly distributed between [0.0,1.1], and the second returns a random integer uniformly distributed between [0,N].
<code> <code>
1> random:uniform(). 1> random:uniform().
-9.23009e-2+0.159112
2> random:uniform(150). 2> random:uniform(150).
67 67
</code> </code>
-This code generates and prints a random integer between 25 and 75, inclusive: +To select random integers from [N,M], can use N+random:uniform(M-N).
-<code>+
-3> io:fwrite("Random = ~B\n", [random:uniform(51) + 24]).+
-Random = 74+
-ok+
-</code>+
- +
-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: +
-<code>+
-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+
-</code>+
-Another common example is generating a random password: +A common example is generating a random password:
<code> <code>
-generate_8_password() ->+generate_password(N) ->
- lists:flatten(lists:foldl(fun(X,AccIn) ->+ lists:map(fun (_) -> random:uniform(90)+$\s+1 end, lists:seq(1,N)).
- [random:uniform(90) + 32|AccIn] end,+
- [], lists:seq(1,8))).+
-7> generate_8_password().+3> generate_password(8).
-"]VD'hEa;"+"l?8j#$&&"
-8> generate_8_password().+4> generate_password(8).
-"Zju!W9'Z"+"V<bFi(EW"
-9> generate_8_password().+5> generate_password(8).
-"uw6uX\"JF"+"irp^DXTz"
-10> generate_8_password().+
-"-)3Ue=8n"+
</code> </code>

Revision as of 10:32, 25 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/0 and random:uniform/1 ; the first returns a random float uniformly distributed between [0.0,1.1], and the second returns a random integer uniformly distributed between [0,N].

1> random:uniform().
0.159112
2> random:uniform(150).
67

To select random integers from [N,M], can use N+random:uniform(M-N).

A common example is generating a random password:

generate_password(N) ->
    lists:map(fun (_) -> random:uniform(90)+$\s+1 end, lists:seq(1,N)).

3> generate_password(8).
"l?8j#$&&"
4> generate_password(8).
"V generate_password(8).
"irp^DXTz"

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.

Erlang/OTP Projects
Personal tools