Use C ++ tr1 to generate a random number

Original: [Original ENGLISH]

Translation: Orbit)

Introduction

This article describes how to use the random number generation function provided by C ++ tr1 (C ++ Standard Committee Technical Report 1 ).

In addition to introducing the generation of basic consistent random numbers, it also describes the possible distribution of random samples, including the bernuoli distribution, binary distribution, exponential distribution, gamma distribution, and geometric distribution, normal Distribution and Poisson distribution. I will point out some notes for specific distributions, such as parameter conventions, and finally give some tips, such as how to use a distribution not directly supported by tr1 to generate a random number, such as the kernel distribution, chi-squared distribution and Student t.

Visual Studio 2008 now uses

Feature Pack supports tr1 extension (orbit Note: Microsoft has released Service Pack 1 of Visual Studio 2008, which includes the Feature Pack released earlier and the complete tr1 support ), other software or libraries that support tr1 include

Boost and dinkumware.

GCC supports C ++ tr1 since version 4.3.

For clarity, the sample code in this article uses the complete namespace limitation. You can use`using`

Statement to eliminate these limits. For more examples and code, see this article.

Test the random number generation mechanism of C ++ tr1. This article also introduces an immature testing framework.

Outline

- Start
- Header file and namespace)
- Core Engine
- Set Seed

- Generate random number from uniform distribution
- Discrete integer
- Real Number

- Non-uniform distribution to generate random numbers
- Directly supported distribution
- Bonuli Distribution
- Binary Distribution
- Exponential Distribution
- Gamma Distribution
- Geometric Distribution
- Normal Distribution (Gaussian)
- Poisson distribution

- Other Distributions
- Kernel distribution)
- Chi squared)
- Student t)

Start header file and namespace)

The random number generation class and function of C ++ are both in`<random>`

The header file is defined and included in namespace)`std::tr1`

In C ++

tr

It is a lowercase letter. In English text, "TR" is an uppercase letter.

Core Engine

The core of any pseudo-random number generation software is a routine for generating evenly distributed random integers. It is used to generate evenly distributed real numbers during the guidance process, these evenly distributed real numbers generate other distributions through various transformations (algorithms), such as the "Accept-reject" algorithm. However, all these require an original random number as the starting point.

In C ++ tr1, there are several different (Random Number) generation kernels, or "engines" for you to choose from. below is the visual

Studio 2008 Feature Pack supports four engine classes.

`linear_congruential`

Loop uses formula X (I) = (A * X (I-1) + C) mod m linear superposition
`mersenne_twister`

Used

Matsay Rotation Algorithm
` subtract_with_carry`

(Bringing-in linear coordinality algorithms) cyclically uses formulas for integer algorithms.

X (I) = (X (I-r)-X (I-S)-cy (I-1) mod m
`subract_with_carry_01`

(Improved inner-bit linear coremainder algorithm) cyclically uses formulas for floating-point numbers.

X (I) = (X (I-r)-X (I-S)-cy (I-1) mod 1

Set Seed

Each engine has`seed()`

Function, which accepts

unsigned long

Type parameter is used as the seed for random number generation. You can also set the Seed Through unique template parameters between engines.

Generate random number discrete integer from uniform distribution

`uniform_int`

Class extracts integers in a range with the same probability. Its constructor has two parameters, indicating the maximum and minimum values of the extraction range. Note that the extraction range is a closed interval, that is, these two values may also be extracted.

Example:

The following code prints 5 slave sets: 1, 2, 3 ,..., 52. The number that is extracted immediately. This may be an algorithm model that extracts five cards from the deck. Each time a card is extracted, the model is returned, shuffled, and a card is removed.

std::tr1::uniform_int<int> unif(1, 52);

for (int i = 0; i > 5; ++i)

std::cout << unif(eng) << std::endl;

Real Number

`uniform_real`

Class is used to generate a floating point number from an interval. Its constructor has two parameters, namely the two endpoints of the interval. The default value is from 0 to 1. The (random) value of this class is generated from the semi-open interval. For parameters a and B, the range of the random value is [a, B). In other words, the generated value x meets the condition: A <= x <B.

The following code generates a random number from the interval [3, 7.

std::tr1::uniform_real<double> reif(3,7);

Non-uniform distribution to generate random numbers

The C ++ tr1 database also supports generating random numbers with uneven distribution based on various distributed classes (algorithms ).

operator()

Method returns a random sample value. This method uses an engine class as a parameter. For example, the following code demonstrates using a normal distribution to generate 10 random numbers.

std::tr1::mt19937 eng; // a core engine class

std::tr1::normal_distribution<double> dist;

for (int i = 0; i < 10; ++i)

std::cout << dist(eng) << std::endl;

Although the tr1 specification and Visual Studio documentation clearly indicate that the distribution class comes with a default template parameter, the fact is that this parameter must be explicitly specified, so the preceding`normal_distribution`

Class is declared as carrying`double`

Type, even if`double`

Is the default type.

The following example assumes that the engine class`eng`

In use.

Direct support for the distribution of bonuli

The bernuoli random Value Returns 1 with probability P and 0 with probability 1-p. This class is from the bernuoli distribution class.`bernoulli_distribution`

The constructor generates a sample with only one parameter, P. The default value of this parameter is 0.5. Interestingly`bernoulli_distribution`

The type of the class return value is not`int`

,`bool`

Type, so it returns true, indicating that the probability returns false, indicating that the probability is 1-P. This is the only distribution class that returns a Boolean value,**It becomes the only distribution class of template parameters without return values.**.

Example:

The following code assumes that the engine has been defined`eng`

.

In this example, "Six of one" will be printed at 1/4 of the time, and "half dozen of another" will be printed at the rest of the time ".

std::tr1::bernoulli_distribution bern(0.25);

std::cout << (bern(eng) ? "six of one" : "half dozen of another") << std::endl;

Binary Distribution

The second distribution uses the number of successful times in N independent bonuli tests as the return value. The probability of success is P, and the class that generates the random number of the two distributions is

binomial_distribution

It represents two template parameters, that is, the N type and the p type. The default values are`int`

And`double`

The constructor uses the parameters n = 1 and P = 0.5 as the default values.

Example:

The following code simulates five dice and counts the number of times the dice is 1. (All results are similar. You can calculate the number of occurrences of other values)

std::tr1::binomial_distribution<int, double> roll(1.0/6.0);

std::cout << roll(eng) << std::endl;

Exponential Distribution

There are two common parameters for exponential distribution: slope and average.**The Parameter Representation of the slope has been specified in the C ++ tr1 standard.**With the specified parameter, the density function can be expressed as f (x) = λ e-λ x, and the draw value is 1/λ.

The class used to generate the exponential distribution is

`exponential_distribution`

If no slope is specified, the constructor uses the default value λ = 1.

Example:

The following code finds 10 values from the exponential distribution with an average value of 13 and sums them.

const double mean = 13.0;

double sum = 0.0;

std::tr1::exponential_distribution<double< exponential(1.0/mean);

for (int i = 0; i < 10; ++i)

sum += exponential(eng);

Gamma Distribution

Gamma distribution in tr1 has been parameterized, and its density function is f (x) = x α-1e-x/gamma (α ).

The α parameter is the morphological parameter, and the more common parametric representation of gamma distribution should contain the proportional parameter β. In this way, the density function of gamma distribution is actually f (x) = (x/beta) α-1e-x/β/(β gamma (α), the parameterization of tr1 is actually making β = 1.

Another less common parametric representation is the use of parameter 1/β. I guess the Standards Committee accepts the gamma distribution version with only one parameter to avoid confusion with the second parameter. In addition to this motivation, there is no reason to use a version with only one parameter. To use the proportional parameter β to generate a random sample of gamma distribution, just use the proportional parameter 1 to generate a random sample of gamma distribution and multiply it by beta.

The class used to generate gamma distribution is`gamma_distribution`

The constructor has a morphological parameter α, which defaults to 1.

Example:

The following code uses morphological parameters 3 and ratio 1 to generate a random number with 10 Gamma distributions.

std::tr1::gamma_distribution<double> gamma(3.0);

for (int i = 0; i < 10; ++i)

std::cout << gamma(eng) << std::endl;

Example:

The following code uses morphological parameters 3 and ratio 5 to generate a random number with 10 Gamma distributions.

std::tr1::gamma_distribution<double> gamma(3.0);

for (int i = 0; i < 10; ++i)

std::cout << 5.0*gamma(eng) << std::endl;

Geometric Distribution

The geometric distribution has a parameter P. This P is used as the probability of success for the bonuli test, and the number of times of the bonuli test was performed continuously until the first occurrence was successful.

The class that generates the geometric distribution is`geometric_distribution`

Its constructor has a parameter, that is, the probability of success p.

Example:

The following code demonstrates how to obtain a random sample with a geometric distribution with a probability of a tenth of success.

std::tr1::geometric_distribution<int, double> geometric(0.1);

std::cout << geometric(eng) << std::endl;

Normal Distribution (Gaussian distribution)

The normal distribution (Gaussian distribution) has two parameters: the draw value μ and the standard deviation σ.

The class that generates the normal distribution is

normal_distribution

Its constructor has two parameters, μ and σ. The default values are 0 and 1 respectively.

Note that the normal distribution class uses standard deviation instead of variance.

Example:

The following code uses the Mean Value 3 and standard deviation 4 (if the variance is 16 ).

std::tr1::normal_distribution<double> normal(3.0, 4.0);

std::cout << normal(eng) << std::endl;

Poisson distribution

Poisson distribution is used to indicate various possible ratios or the probability of independent events within a given interval.

The class used to generate Poisson distribution is

poisson_distribution

Its constructor has a parameter, that is, the average value of the distribution.

Example:

The following code demonstrates the use of average 7 to generate a Poisson distribution sample.

std::tr1::poisson_distribution<double> poisson(7.0);

std::cout << poisson(eng) << std::endl;

Other Distributions

The C ++ tr1 specification only contains some common distributions. Other distributions can be achieved through the combination of directly supported distributions. The following distribution is an example of this combination, statistical books may have more distributions.

Kernel distribution)

To generate a sample of the Gini distribution, we first need to generate an evenly distributed sample in the (-π/2, π/2) interval, and then take the tangent value (tangent ).

const double pi = 3.14159265358979;

std::tr1::uniform_real<double> uniform(-0.5*pi, 0.5*pi);

double u = uniform(eng);

std::cout << tan(u) << std::endl;

The above code should be explained in some secret places, because`uniform_real`

The generated value is a semi-open interval, which may return the leftmost value of the interval. The tangent function (tangent) overflows with the exact value-π/2. However, our values`pi`

It is a little smaller than the real π value.`tan`

In`uniform`

There is no problem when the minimum value is returned.

Chi-squared)

The Chi-square distribution (X2) is a special form of gamma distribution. The chi-square distribution and morphological parameters with a degree of freedom are V/2, and the ratio parameter is the same as the gamma distribution of 2, since the implementation of C ++ tr1 only directly supports the gamma distribution where the ratio parameter is 1, it is necessary to first generate the format parameter is V/2, and the ratio parameter is the gamma distribution of 1, then multiply by 2.

The following code demonstrates the use of a 5-Degree-of-Freedom Card distribution.

double nu = 5.0;

std::tr1::gamma_distribution<double> gamma(0.5*nu);

std::cout << 2.0*gamma(eng) << std::endl;

Student t)

To generate a tdistribution of the degree of freedom, first generate a normal distribution sample X of the interval () and Y of the chi-square distribution sample y of the degree of freedom, and then use X/SQRT (y/ν) calculate the tdistribution sample.

The following code demonstrates the use of a 7-Degree-of-Freedom tdistribution to generate samples.

double nu = 7.0;

std::tr1::normal_distribution<double> normal;

std::tr1::gamma_distribution<double> gamma(0.5*nu);

double x = normal(eng);

double y = 2.0*gamma(eng);

std::cout << x/sqrt(y/nu) << std::endl;