• No se han encontrado resultados

A random number generator (RNG) is a procedure that can be invoked repeat- edly to produce a sequenceU0,U1,. . . of random variates with certain properties described later.

Most operating systems and language libraries contain RNGs based on the linear

congruential (LC) method. The method uses a (global static) variables that is initialized with a value called the seed. Each time the RNG is called, the procedure applies an arithmetic formula tos, and the result becomes the new value of s that is returned by the procedure.

The example LC procedure shown in Figure 5.2 applies an arithmetic function tos using three constants a, b, and m. (The term linear congruential refers to this function family.) The% denotes the modulus operator, which returns the integer

static long s;

void rngInitial(long seed) {s = seed;} long random() { long a = 1664525; long b = 1013904223; long m = 2ˆ32; s = (a*s+b) % m; return s; }

Figure 5.2. A random number generator. This is an example of a linear congruential generator.

remainder from dividing(a*s + b) by m. The modulus operation ensures that s is always between 0 and m-1.

The values ofa, b, and m must be carefully chosen according to number-theoretic principles to ensure that good random sequences are generated. The combination is from Numerical Recipes [16]; others may be found in Knuth [10] and L’Ecuyer [12].

An integer in the range[0,m−1] can be converted to a real number in the range [0,1) (the bracket notation means including 0 but not including 1) by dividing by

m. Many software libraries contain generators that use this technique, with m set

to a very large number, to return floats and doubles instead of integers and longs. In this section we refer to specific generator types withrngInt(m), which returns a random int or long in[0,m − 1], and rngReal(), which returns a random float or double in[0,1).

LetU0 denote the initial seed value, and letU1,U2. . . denote the sequence of uniform random variates returned by successive calls to a given RNG. Generators

of uniform random variates are evaluated according to two properties:

1. Uniformity. Each possible integer in[0,m − 1] is equally likely to be generated as the nextUi.

2. Independence. The probability thatUi takes a particular valueu∈ [0,m − 1]

does not depend on previous variatesU0. . . Ui−1.

All linear congruential methods, and indeed all computer-based random number generators, fail property 2, because each variateUi depends exactly on the value

of the previous variateUi−1. For this reason LC generators are technically called pseudorandom number generators, although the distinction is often ignored in

Pseudorandom generators are evaluated according to how well they mimic a true (theoretical) source of independent uniform variates. A good RNG has a long

period, which means it runs for a long time before repeating a value – a maximum

period ofm is ideal but not always realized. The RNG is also expected to pass tests

of uniformity and randomness. A standard collection of statistical tests has been developed to test property 1 and to detect patterns in theUisequence that would be

unusual in a truly independent source of variates. These tests look at, for example, the lengths of “runs” above and below the mean, the lengths of monotonically increasing and decreasing sequences, distributions of poker hands that encode the variates, and so forth. See Knuth [10] for a survey of these tests.

The linear congruential RNGs available nowadays in most systems are consid- ered adequate for many but not all purposes; see [15] for a survey of common features and problems. Here are some tips for making best use of them.

• Initialize with a big integer seed value, ideally using as many digits as the type allows. Small integer seeds create sequences that start out less random but improve as more variates are generated. If the initial seed value cannot be controlled (because it is set by a procedure external to the test program, for example), run the RNG for several iterations to get past initial conditions. • The low-order bits of integers generated by LC methods are less random than

the high-order bits. To mimic, say, a coin toss with a random sequence of 0’s and 1’s, do not use a formula based on low-order bits, such asr = rngInt() % 2. On some systems this could produce a strictly alternating sequence of 0’s and 1’s, or a sequence of all 1’s. Instead use the high order bits:

if (rngReal() < 0.5) r=0; else r=1;

• Linear congruential generators tend to exhibit patterns of serial correlation (a type of nonrandomness) within short subsequences. For example, assigning

(Ui,Ui+1,Ui+2) in sequence to create random points in 3-space can yield sets of points that line up on hyperplanes. To avoid this problem when generating random points in D-space, use different RNG streams with separate seeds for each dimension; apply a combination of scrambling and skipping operations to break up patterns in short sequences; or use a different category of RNG, such as a linear feedback shift register (LFSR). See Knuth [10] for an introduction to LFSR generators.

• A common technique for initializing the seed is to call the (Unix) system time command, which returns a long integer recording accumulated clock ticks since some startup date. If two calls to the time command occur in succession, the clock may not have had a chance to advance.

• Linear congruential methods should never be used as a source of random num- bers in cryptographic applications, because the generating function is too easy to guess. They can also create problems in experiments that require huge numbers of variates – more than the period allows – and/or a high degree of statisti- cal precision in the results. For these applications alternative generators (more random, but slower) are recommended.

All other categories of random variates for computational experiments are created by algorithms that transform or combine sequences of uniform variates generated by RNGs. Here are two simple one-line transformations.

• To generate an integer I uniformly in the range [a,b] (inclusive), use I = a + (int) (rngReal()*(b-a+1));

• To generate a real R in the range [a,b) use the formula R = a + rngReal() * (b-a);

Even if a given RNG passes all tests of randomness, some small pattern of nonrandomness could be magnified by such a transformation, in such a way that the experimental outcomes are artifacts of the RNG and not reflective of “true” (theoretical) properties. It is always wise to replicate key experimental results by substituting a different RNG and comparing the outputs.

Documento similar