📄 nr02doc.htm
字号:
</tr> <tr> <td width="50%" valign="top">Microsoft 5.0, 6.0, 7.0</td> <td width="50%" valign="top">OK</td> </tr> <tr> <td width="50%" valign="top">Watcom 10A</td> <td width="50%" valign="top">OK</td> </tr> <tr> <td width="50%" valign="top">Sun CC 6</td> <td width="50%" valign="top">OK</td> </tr> <tr> <td width="50%" valign="top">Gnu G++ 2.96 (Linux), 2.95 (Sun)</td> <td width="50%" valign="top">OK</td> </tr> <tr> <td width="50%" valign="top">Intel 5 for Windows or Linux</td> <td width="50%" valign="top">OK</td> </tr></table><p>I have included make files for Borland 5.5, CC and Gnu G++. See <a href="#files">files</a>section. You can use my <a href="genmake.htm">genmake</a> program to generate make files for other compilers.</p><h3><a name="testing"></a>Testing</h3><p>The files tryrand.cpp, tryrand1.cpp, tryrand2.cpp, tryrand3.cpp, tryrand4.cpp, tryrand5.cpp, hist.cpprun the generators in the library and print histograms of the resulting distributions.Sample means and variances are also calculated and can be compared with the populationvalues. The results from Borland 5.5 are in tryrand.txt. Other compilers may give different but still correct results. In particular, Microsoft C++ compilers give different results when global optimisation is set. This is most likely due to different round-off error but may also be due to different order of evaluation of expressions. The appearance of the histograms in the output should be similar to that in tryrand.txt and the statistical tests should still be passed. There are some notes in tryrand.txt for assessing the output. </p><table BORDER="1" WIDTH="100%"> <tr> <td WIDTH="100%">If you are compiling on a PC with a 16 bit compiler you will need to set <i>n_large</i> to be 8000 rather than 1000000 and <i>n</i> to 8000 rather than 200000 in tryrand.cpp. This will change the output from the test program from that given in tryrand.txt although the general appearance should be the same.</td> </tr></table><p>The test program tryrand.cpp includes a simple test for memory leaks. This is valid foronly some compilers. It seems to work for Borland C++ in console mode but not for Gnu G++or Microsoft C++, where it almost always (presumably incorrectly) suggests an error. </p><p> </p><h2><a NAME="description"></a>Descriptions of the classes to beaccessed by the user:</h2><h3><a NAME="random"></a>Random:</h3><p>This is the basic uniform random number generator, used to drive all the others. TheLewis-Goodman-Miller algorithm is used with Marsaglia mixing. While not perfect, and nowsuperseded, the LGM generator has given me acceptable results in a wide variety ofsimulations. See <i>Numerical Recipes in C</i> by Press, Flannery, Teukolsky, Vetterlingpublished by the Cambridge University Press for details. The LGM generator does pass theMarsaglia <i><a HREF="http://stat.fsu.edu/~geo/diehard.html">diehard</a></i> tests whenyou include the mixing. (It doesn't pass without the mixing). Nevertheless it should beupgraded. It is very dubious if you are going to call it more than 100 million times in a simulation. Ideally the basic generator should be recoded in assembly language to give themaximum speed to all the generators in this package. You can access the numbers directlyusing <tt>Next()</tt> but I suggest you use class <a HREF="#uniform">Uniform</a> foruniform random numbers and reserve Random for setting the starting seed and as the baseclass for the random number generators.</p><p>Remember that you need to call <tt>Random::Set(double seed)</tt> at the beginning of your program. See the <a href="#overview">overview</a> and tryrand.cpp.</p><h3><a NAME="uniform"></a>Uniform:</h3><p>Return a uniform random number from the range (0, 1). The constructor has noparameters. For example </p><pre> Uniform U; for (int i=0; i<100; i++) cout << U.Next() << "\n";</pre><p>prints a column of 100 numbers drawn from a uniform distribution. </p><h3><a NAME="constant"></a>Constant:</h3><p>This returns a constant. The constructor takes one <i>Real</i> parameter; the value ofthe constant to be returned. So </p><pre> Constant C(5.5); cout << C.Next() << "\n";</pre><p>prints 5.5. </p><h3><a NAME="exponential"></a>Exponential:</h3><p>This generates random numbers with density <tt>exp(-x)</tt> for <tt>x>=0</tt>. Theconstructor takes no arguments. </p><pre> Exponential E; for (int i=0; i<100; i++) cout << E.Next() << "\n";</pre><h3><a NAME="cauchy"></a>Cauchy:</h3><p>Generates random numbers from a standard Cauchy distribution. The constructor takes noparameters. </p><pre> Cauchy C; for (int i=0; i<100; i++) cout << C.Next() << "\n";</pre><h3><a NAME="normal"></a>Normal:</h3><p>Generates standard normal random numbers. The constructor has no arguments. This classhas been augmented to ensure only one copy of the arrays generated by the constructorexist at any given time. That is, if the constructor is called twice (before thedestructor is called) only one copy of the arrays is generated. </p><pre> Normal Z; for (int i=0; i<100; i++) cout << Z.Next() << "\n";</pre><h3><a NAME="chisq"></a>ChiSq:</h3><p>Non-Central chi-squared distribution. The method uses ChiSq1 to generate thenon-central part and Gamma2 or Exponential to generate the central part. The constructortakes as arguments the number of degrees of freedom <tt>(>=1)</tt> and thenon-centrality parameter (omit if zero). </p><pre> int df = 10; Real noncen = 2.0; ChiSq CS(df, noncen); for (int i=0; i<100; i++) cout << CS.Next() << "\n";</pre><h3><a NAME="gamma"></a>Gamma:</h3><p>Gamma distribution. The constructor takes the shape parameter as argument. Uses Gamma1,Gamma2 or Exponential. </p><pre> Real shape = 0.75; Gamma G(shape); for (int i=0; i<100; i++) cout << G.Next() << "\n";</pre><h3><a NAME="pareto"></a>Pareto:</h3><p>Pareto distribution. The constructor takes the shape parameter as argument. I followthe definition of Kotz and Johnson's <i>Continuous univariate distributions 1</i>, chapter19, page 234, with <i>k</i> = 1. The generator uses a power transform of a uniform randomnumber. </p><pre> Real shape = 0.75; Pareto P(shape); for (int i=0; i<100; i++) cout << P.Next() << "\n";</pre><h3><a NAME="poisson"></a>Poisson:</h3><p>Poisson distribution: uses Poisson1 or Poisson2. Constructor takes the mean as itsargument. </p><pre> Real mean = 5.0; Poisson P(mean); for (int i=0; i<100; i++) cout << (int)P.Next() << "\n";</pre><h3><a NAME="binomial"></a>Binomial:</h3><p>Binomial distribution: uses Binomial1 or Binomial2. Constructor takes <i>n</i> and <i>p</i>as its arguments. </p><pre> int n = 50; Real p = 0.25; Binomial B(n, p); for (int i=0; i<100; i++) cout << (int)B.Next() << "\n";</pre><h3><a NAME="negativebinomial"></a>NegativeBinomial:</h3><p>Negative binomial distribution. Constructor takes <i>N</i> and <i>P</i> as itsarguments. I use the notation of Kotz and Johnson's <i>Discrete distributions</i>. Somepeople use <i>p</i> = 1/(<i>P</i>+1) in place of the second parameter. </p><pre> Real N = 12.5; Real P = 3.0; NegativeBinomial NB(N, P); for (int i=0; i<100; i++) cout << (int)NB.Next() << "\n";</pre><h3><a NAME="posgenx"></a>PosGenX:</h3><p>This uses an arbitrary density satisfying the previous conditions to generate randomnumbers from that density. Suppose <tt>Real pdf(Real)</tt> is the density. Then use <tt>pdf</tt>as the argument of the constructor. For example </p><pre> PosGenX P(pdf); for (int i=0; i<100; i++) cout << P.Next() << "\n";</pre><table BORDER="1" WIDTH="100%"> <tr> <td WIDTH="100%">Note that the probability density <i>pdf</i> must drop to exactly 0 for the argument large enough. For example, include a statement in the program for <i>pdf</i> that, if the value is less than 1.0E-15, then return 0.</td> </tr></table><h3><a NAME="symgenx"></a>SymGenX:</h3><p>This corresponds to PosGenX for symmetric distributions. <br> </p><table BORDER="1" WIDTH="100%"> <tr> <td WIDTH="100%">Note that the probability density <i>pdf</i> must drop to exactly 0 for the argument large enough. For example, include a statement in the program for <i>pdf</i> that, if the value is less than 1.0E-15, then return 0.</td> </tr></table><h3><a NAME="asymgenx"></a>AsymGenX:</h3><p>Corresponds to PosGenX. The arguments of the constructor are the name of the densityfunction and the location of the mode. </p><pre> Real pdf(Real); Real mode; ..... AsymGenX X(pdf, mode); for (int i=0; i<100; i++) cout << X.Next() << "\n";</pre><table BORDER="1" WIDTH="100%"> <tr> <td WIDTH="100%">Note that the probability density <i>pdf</i> must drop to exactly 0 for the argument large (large positive and large negative) enough. For example, include a statement in the program for <i>pdf</i> that, if the value is less than 1.0E-15, then return 0.</td> </tr></table><h3><a NAME="posgen"></a>PosGen:</h3><p>PosGen is not used directly. It is used as a base class for generating a random numberfrom an arbitrary probability density <tt>p(x)</tt>. <tt>p(x)</tt> must be non-zero onlyfor <tt>x>=0</tt>, be monotonically decreasing for <tt>x>=0</tt>, and be finite. Forexample, <tt>p(x)</tt> could be <tt>exp(-x)</tt> for <tt>x>=0</tt>. </p><p>The method is to cover the density in a set of rectangles of equal area as in thediagram (indicated by <tt>---</tt>). </p><pre> <b>|</b> <b>x</b> <b>|xx</b>------ <b>|</b> <b>xx</b> | <b>|</b> <b>xxx</b> | <b>|</b>.......<b>xxx</b>--------- <b>|</b> | <b>xxxx</b> | <b>|</b> | <b>xxxx</b> | <b>|</b> |.........<b>xxxxx</b>------------ <b>|</b> | | <b>xxxxx</b> | <b>|</b> | | <b>xxxxxx</b> | <b>|</b> | |..............<b>xxxxxx</b>---------------------- <b>|</b> | | | <b>xxxxxxx</b> | <b>|</b> | | | <b>xxxxxxx</b> | <b>|</b> | | | <b>xxxxxxxx</b>| <b>+===========================================================================</b></pre><p>The numbers are generated by generating a pair of numbers uniformly distributed overthese rectangles and then accepting the <i>X</i> coordinate as the next random number ifthe pair corresponds to a point below the density function. The acceptance can be done intwo stages, the first being whether the number is below the dotted line. This means thatthe density function need be checked only very occasionally and on the average only justover 3 uniform random numbers are required for each of the random numbers produced by thisgenerator. </p><p>See PosGenX or Exponential for the method of deriving a class to generate randomnumbers from a given distribution. <br> </p><table BORDER="1" WIDTH="100%"> <tr> <td WIDTH="100%">Note that the probability density <i>p(x)</i> must drop to exactly 0 for the argument, <i>x</i>, large enough. For example, include a statement in the program for <i>p(x)</i> that, if the value is less than 1.0E-15, then return 0.</td> </tr></table><h3><a NAME="symgen"></a>SymGen:</h3>
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -