REBOL 3 Docs Guide Concepts Functions Datatypes Errors
  TOC < Back Next >   Updated: 3-Aug-2010 Edit History  

REBOL 3 Functions: random

random  value  /seed  /secure  /only

Returns a random value of the datatype or shuffles series (modifies).

Arguments:

value - Maximum value of result

Refinements:

/seed - Restart or randomize

/secure - Returns a cryptographically secure random number

/only - Pick a random value from a series

See also:

checksum   now  

Description

The value passed can be used to restrict the range of the random result. For integers random begins at one, not zero, and is inclusive of the value given. (This conforms to the indexing style used for all series datatypes, allowing random to be used directly with functions like PICK.)

loop 3 [print random 10]
1
5
3
lunch: ["Italian" "French" "Japanese" "American"]
print pick lunch random 4
American

If the given argument is a logic value, the result is actually the same as the result of the expression

even? random 2

Example

loop 4 [print random true]
false
false
false
true
loop 2 [print random 1:00:00]
0:12:20
0:48:22

For decimal value the function generates a uniformly distributed random number between zero (inclusive) and the given value (inclusive).

loop 3 [print random 1.0]
0.209417212061865
0.878424991742667
0.93627033045037

Main properties:

  1. the probability density in the interior points is the reciprocal of the given decimal VALUE argument
  2. the probability density in the exterior points is 0.0
  3. as specified by IEEE754, the bounds represent "close" interior well as "close" exterior real numbers. Therefore, the frequency of every bound corresponds to the length of the segment containing adjacent interior real values (real numbers, that are IEEE 754 - rounded to the value of the bound) multiplied by the interior density equal to the reciprocal of the given VALUE

RANDOM can also be used on all series datatypes:

print random "abcdef"
dbcafe
print random [1 2 3 4 5]
2 4 5 3 1

In this case RANDOM randomly shuffles the given series "in place", yielding the original series with the same elements, just shuffled. To cut it down, you can use CLEAR:

key: random "abcdefghijklmnopqrstuv0123456789"
clear skip key 6
print key
anfruk

Here's an example password generator. Add more partial words to get more variations:

syls: ["ca" "ru" "lo" "ek" "-" "." "!"]
print rejoin random syls
.!ru-ekcalo

To initialize the random number generator, you can seed it with a value (to repeat the sequence) or the current time to start a unique seed.

random/seed 123

random/seed now

That last line is a good example to provide a fairly random starting value for the random number generator.

The /SECURE variant uses SHA1() of a repeating pattern of the integer bytes (20 bytes total) and it produces cryptographically secure 64-bit random numbers. Cryptographical security means, that it is infeasible to compute the state of the generator from its output. If you don't need to make computing of the generator state infeasible (needed especially when you use the generator to generate passwords, challenges, etc. and want to comply to the FIPS security standards), it is more efficient to use the raw variant (without /SECURE refinement). Even in that case it is not feasible to compute the state, since the state of present generator consists of too many bits to be computable from the output.

Algorithm

The RANDOM function uses a random generator by Donald E. Knuth adjusted to generate 62-bit random integers. Thus, the maximal obtainable random number is 2 to the power of 62 = 4611686018427387904.

If the RANDOM function obtains 0 as an argument, it yields 0. If the argument is a positive integer, the RANDOM function uses rejection, rejecting all "raw randoms" that exceed the largest obtainable multiple of the given VALUE argument. This way, the uniformity of the distribution is assured. In case the given VALUE exceeds the biggest obtainable "raw random", we would have to reject every "raw random" number, so in that case an overflow error is caused (It certainly is an error expecting a bigger random, than the "raw random" maximum).

If the given VALUE is negative, then the generated random integers are in the interval VALUE <= R <= -1.

Uniformly distributed random decimals are generated using the integer output of the Knuth's generator as follows:

tt62: to integer! 2 ** 62
4611686018427387904
random-dec: func [x [decimal!]] [(to decimal! (random tt62) - 1) / tt62 * x]

random/seed 0
random 1.0
0.209417212061865
random/seed 0
random-dec 1.0
0.209417212061865

In case the given decimal VALUE is positive, the generated random deviates are uniformly distributed in the interval 0.0 <= R <= VALUE, i.e. including bounds.

In case the given decimal VALUE is negative, the random deviates are uniformly distributed in the interval VALUE <= R <= 0.0.

Sometimes we need to obtain a uniformly distributed random number R, such that 0.0 < R < 1.0 (i.e. a uniformly distributed random number in the given interval, excluding the bounds). We can get such an R rejecting the bounds as follows:

random/seed 0
until [
    r: random 1.0
    all [
        r !== 0.0
        r !== 1.0
    ]
]
r
0.209417212061865


  TOC < Back Next > REBOL.com - WIP Wiki Feedback Admin