1
0
Fork 0
cl-sites/www.cs.cmu.edu/Groups/AI/html/cltl/clm/node133.html

211 lines
11 KiB
HTML
Raw Normal View History

2023-10-25 11:23:21 +02:00
<!DOCTYPE HTML PUBLIC "-//W3O//DTD W3 HTML 2.0//EN">
<!Converted with LaTeX2HTML 0.6.5 (Tue Nov 15 1994) by Nikos Drakos (nikos@cbl.leeds.ac.uk), CBLU, University of Leeds >
<HEAD>
<TITLE>12.9. Random Numbers</TITLE>
</HEAD>
<BODY>
<meta name="description" value=" Random Numbers">
<meta name="keywords" value="clm">
<meta name="resource-type" value="document">
<meta name="distribution" value="global">
<P>
<b>Common Lisp the Language, 2nd Edition</b>
<BR> <HR><A NAME=tex2html3187 HREF="node134.html"><IMG ALIGN=BOTTOM ALT="next" SRC="icons/next_motif.gif"></A> <A NAME=tex2html3185 HREF="node121.html"><IMG ALIGN=BOTTOM ALT="up" SRC="icons/up_motif.gif"></A> <A NAME=tex2html3179 HREF="node132.html"><IMG ALIGN=BOTTOM ALT="previous" SRC="icons/previous_motif.gif"></A> <A NAME=tex2html3189 HREF="node1.html"><IMG ALIGN=BOTTOM ALT="contents" SRC="icons/contents_motif.gif"></A> <A NAME=tex2html3190 HREF="index.html"><IMG ALIGN=BOTTOM ALT="index" SRC="icons/index_motif.gif"></A> <BR>
<B> Next:</B> <A NAME=tex2html3188 HREF="node134.html"> Implementation Parameters</A>
<B>Up:</B> <A NAME=tex2html3186 HREF="node121.html"> Numbers</A>
<B> Previous:</B> <A NAME=tex2html3180 HREF="node132.html"> Byte Manipulation Functions</A>
<HR> <P>
<H1><A NAME=SECTION001690000000000000000>12.9. Random Numbers</A></H1>
<P>
<A NAME=RANDOM>The</A>
Common Lisp facility for generating pseudo-random numbers has
been carefully defined to make its use reasonably portable.
While two implementations may produce different series
of pseudo-random numbers, the distribution of values should
be relatively independent of such machine-dependent aspects
as word size.
<P>
<BR><b>[Function]</b><BR>
<tt>random <i>number</i> &amp;optional <i>state</i></tt><P><tt>(random <i>n</i>)</tt> accepts a positive number <i>n</i> and returns
a number of the same kind between zero (inclusive) and <i>n</i> (exclusive).
The number <i>n</i> may be an integer or a floating-point number.
An approximately uniform choice distribution is used.
If <i>n</i> is an integer, each of the possible results
occurs with (approximate) probability <br>1/<i>n</i>.
(The qualifier ``approximate'' is used because of implementation
considerations; in practice, the deviation from uniformity should be
quite small.)
<P>
The argument <i>state</i> must be an object of type <tt>random-state</tt>;
it defaults to the value of the variable <tt>*random-state*</tt>.
This object is used to maintain the state of the pseudo-random-number
generator and is altered as a side effect of the <tt>random</tt> operation.
<P>
<hr>
<b>Compatibility note:</b> <tt>random</tt> of zero arguments as defined in MacLisp
has been omitted because
its value is too implementation-dependent (limited by fixnum range).
<hr>
<b>Implementation note:</b> In general, even if <tt>random</tt> of zero arguments
were defined as in MacLisp,
it is not adequate to define <tt>(random <i>n</i>)</tt> for integral <i>n</i>
to be simply <tt>(mod (random) <i>n</i>)</tt>; this fails to be uniformly distributed
if <i>n</i> is larger than the largest number produced by <tt>random</tt>,
or even if <i>n</i> merely approaches this number.
This is another reason for omitting <tt>random</tt> of zero arguments in Common Lisp.
Assuming that the underlying mechanism produces ``random bits''
(possibly in chunks such as fixnums), the best approach is to produce
enough random bits to construct an integer <i>k</i> some number <i>d</i> of bits
larger than <tt>(integer-length <i>n</i>)</tt> (see <tt>integer-length</tt>), and
then compute <tt>(mod <i>k</i> <i>n</i>)</tt>. The quantity <i>d</i> should be at
least 7, and preferably 10 or more.
<P>
To produce random floating-point numbers in the half-open
range [<i>A</i>, <i>B</i>),
accepted practice (as determined by a look through the
<i>Collected Algorithms from the ACM</i>, particularly algorithms
133, 266, 294, and 370) is to compute <br><i>X</i> * (<i>B</i> - <i>A</i>) + <i>A</i>,
where <i>X</i> is a floating-point number uniformly distributed over
[0.0, 1.0)
and computed by calculating a random integer <b><i>N</i></b> in the range
[0, <i>M</i>)
(typically by a multiplicative-congruential or linear-congruential method
mod <b><i>M</i></b>) and then setting <i>X</i> = <i>N/M</i>. See also [<A HREF="node368.html#KNUTHVOLUME2">27</A>].
If one takes <IMG ALIGN=BOTTOM ALT="" SRC="_24769_tex2html_wrap41899.gif">, where <b><i>f</i></b> is the length of the significand
of a floating-point number (and it is in fact common to choose <b><i>M</i></b>
to be a power of 2), then this method is equivalent to the following
assembly-language-level procedure. Assume the representation
has no hidden bit. Take a floating-point 0.5,
and clobber its entire significand with random bits. Normalize the
result if necessary.
<P>
For example, on the DEC PDP-10, assume that accumulator <tt>T</tt> is completely random
(all 36 bits are random). Then the code sequence
<P><pre>
LSH T,-9 ;Clear high 9 bits; low 27 are random
FSC T,128. ;Install exponent and normalize
</pre><P>
will produce in <tt>T</tt> a random floating-point number uniformly distributed
over [0.0, 1.0). (Instead of the <tt>LSH</tt> instruction,
one could do
<P><pre>
TLZ T,777000 ;That's 777000 octal
</pre><P>
but if the 36 random bits came from a congruential random-number generator,
the high-order bits tend to be ``more random'' than the low-order ones,
and so the <tt>LSH</tt> would be better for uniform distribution.
Ideally all the bits would be the result of high-quality randomness.)
<P>
With a hidden-bit representation, normalization is not a problem,
but dealing with the hidden bit is. The method can be adapted as follows.
Take a floating-point 1.0 and clobber the explicit significand bits with
random bits; this produces a random floating-point number in
the range [1.0, 2.0). Then simply subtract 1.0. In effect, we
let the hidden bit creep in and then subtract it away again.
<P>
For example, on the DEC VAX, assume that register <tt>T</tt> is
completely random (but a little less random than on the PDP-10, as
it has only 32 random bits). Then the code sequence
<P><pre>
INSV #^X81,#7,#9,T ;Install correct sign bit and exponent
SUBF #^F1.0,T ;Subtract 1.0
</pre><P>
will produce in <tt>T</tt> a random floating-point number uniformly distributed
over [0.0, 1.0). Again, if the low-order bits are not random enough,
then the instruction
<P><pre>
ROTL #7,T
</pre><P>
should be performed first.
<P>
Implementors may wish to consult reference [<A HREF="node368.html#ADDITIVERANDOMS">41</A>] for
a discussion of some efficient methods of generating pseudo-random numbers.
<hr>
<P>
<BR><b>[Variable]</b><BR>
<tt>*random-state*</tt><P>This variable holds a data structure,
an object of type <tt>random-state</tt>, that encodes the internal state
of the random-number generator that <tt>random</tt> uses by default.
The nature
of this data structure is implementation-dependent. It may be
printed out and successfully read back in, but may or may not function
correctly as a random-number state object in another implementation.
A call to <tt>random</tt> will perform a side effect on this data structure.
Lambda-binding this variable to a different random-number state object
will correctly save and restore the old state object.
<P>
<BR><b>[Function]</b><BR>
<tt>make-random-state &amp;optional <i>state</i></tt><P>This function returns a new object of type <tt>random-state</tt>,
suitable for use as the value of the variable <tt>*random-state*</tt>.
If <i>state</i> is <tt>nil</tt> or omitted, <tt>make-random-state</tt> returns a <i>copy</i>
of the current random-number state object (the value of
the variable <tt>*random-state*</tt>). If <i>state</i> is a state object,
a copy of that state object is returned. If <i>state</i> is <tt>t</tt>,
then a new state object is returned that has been ``randomly''
initialized by some means (such as by a time-of-day clock).
<P>
<hr>
<b>Rationale:</b> Common Lisp purposely provides no way to initialize a <tt>random-state</tt>
object from a user-specified ``seed.'' The reason for this is that
the number of bits of state information in a <tt>random-state</tt> object
may vary widely from one implementation to another, and there is no
simple way to guarantee that any user-specified seed value will be
``random enough.'' Instead, the initialization of <tt>random-state</tt>
objects is left to the implementor in the case where the argument <tt>t</tt>
is given to <tt>make-random-state</tt>.
<P>
To handle the common situation of executing the same program many times
in a reproducible manner, where that program uses <tt>random</tt>, the following
procedure may be used:
<OL><LI>
Evaluate <tt>(make-random-state t)</tt> to create a <tt>random-state</tt> object.
<P>
<LI>
Write that object to a file, using <tt>print</tt>, for later use.
<P>
<LI>
Whenever the program is to be run, first use <tt>read</tt> to create
a copy of the <tt>random-state</tt> object from the printed representation
in the file.
Then use the <tt>random-state</tt> object newly created by the <tt>read</tt> operation
to initialize the random-number generator for the program.
</OL>
It is for the sake of this procedure for reproducible execution that
implementations are required to provide a read/print syntax for objects
of type <tt>random-state</tt>.
<P>
It is also possible to make copies of a <tt>random-state</tt> object
directly without going through the print/read process, simply by
using the <tt>make-random-state</tt> function to copy the object; this allows
the same sequence of random numbers to be generated many times
within a single program.
<hr>
<b>Implementation note:</b> A recommended way to implement the type <tt>random-state</tt>
is effectively to use the machinery for <tt>defstruct</tt>.
The usual structure syntax may then be used for printing <tt>random-state</tt>
objects; one might look something like
<pre>
#S(RANDOM-STATE DATA #(14 49 98436589 786345 8734658324 ...))
</pre>
where the components are of course completely implementation-dependent.
<hr>
<P>
<BR><b>[Function]</b><BR>
<tt>random-state-p <i>object</i></tt><P><tt>random-state-p</tt> is true if its argument is a random-state object,
and otherwise is false.
<P><pre>
(random-state-p <i>x</i>) == (typep <i>x</i> 'random-state)
</pre><P>
<P>
<BR> <HR><A NAME=tex2html3187 HREF="node134.html"><IMG ALIGN=BOTTOM ALT="next" SRC="icons/next_motif.gif"></A> <A NAME=tex2html3185 HREF="node121.html"><IMG ALIGN=BOTTOM ALT="up" SRC="icons/up_motif.gif"></A> <A NAME=tex2html3179 HREF="node132.html"><IMG ALIGN=BOTTOM ALT="previous" SRC="icons/previous_motif.gif"></A> <A NAME=tex2html3189 HREF="node1.html"><IMG ALIGN=BOTTOM ALT="contents" SRC="icons/contents_motif.gif"></A> <A NAME=tex2html3190 HREF="index.html"><IMG ALIGN=BOTTOM ALT="index" SRC="icons/index_motif.gif"></A> <BR>
<B> Next:</B> <A NAME=tex2html3188 HREF="node134.html"> Implementation Parameters</A>
<B>Up:</B> <A NAME=tex2html3186 HREF="node121.html"> Numbers</A>
<B> Previous:</B> <A NAME=tex2html3180 HREF="node132.html"> Byte Manipulation Functions</A>
<HR> <P>
<HR>
<P><ADDRESS>
AI.Repository@cs.cmu.edu
</ADDRESS>
</BODY>