A TR1 Tutorial: Generating Random Numbers

TR1 brings a new header into the standard library. called <random>. It defines several random number generators. Until TR1, the only way to generate random numbers in C++ was by using the rand() function. This function, although quite trivial to use and good enough for most of the applications, is not suitable for some applications. For them, developers had to rely on third-party libraries or generators, such as the Marsenne Twister. TR1 defines several good random generators, including the Marsenne twister.

Unfortunately, documentation for these generators is not very good, and MSDN lacks in examples. In this article, I will try to clarify how to use these generators, at least for simple usage.

What Is a Generator?

A random number generator, contrary to a first impression, does not generate truly random numbers, but pseudo-random. Generating numbers imply executing an algorithm, each new number depending one way or another on the last generator number (or a number or more from previous iterations). That means any such algorithm needs an initial value, called a "seed." An algorithm initialized with the same seed will generate the same sequence of numbers. This is an important aspect because, in practice people, forget to initialize the generator. Being an algorithm based on formulas, a generator is deterministic, and the number it generates is also deterministic. Only a hardware device can generate truly random numbers.

Before TR1

As I mentioned before, until TR1, the only "standard" way for generating random numbers was by using the rand() function. The following example shows how to generate numbers in the interval [0, 9].

int main()
{
   // seeding the generator
   srand((unsigned int)time(NULL));

   // generate 10 "random" numbers
   for(int i = 0; i < 10; ++i)
   {
      std::cout << rand()%10 << " ";
   }
   std::cout << std::endl;

   return 0;
}

The first step was to initialize the generator; a common practice (and probably the best) is to use the value returned by the time() function, which is the number of seconds passed since January 1, 1970. If this seeding is forgotten, all the generated sequences will be identical (each time you run the program, the same numbers will be generated).

You also have to pay attention not to call srand(), as shown above, twice in less than a second because, in that case, time() returns the same value and you run into the same problem.

What's New in TR1?

TR1 introduces three types of 'entities': generators, engines, and distributions. A generator is an object that generates pseudo-random numbers. A generator that generates numbers with a uniform distribution is called an engine. Engines and distributions can be combined to generate numbers in two ways:

  • Providing an engine to the operator() of a distribution class, or
  • Using the variate_generator class to associate a generator and a distribution

Engines

An engine is basically a data source of uniformly distributed numbers in a specific interval. All engines provide the following functions:

  • min(): Gives the minimum value that can be returned by engine's operator();
  • max(): Gives the maximum value that can be returned by engine's operator();
  • operator(): Returns values uniformly distributed between min() and max();
  • seed(): Initializes the engine with a start value; this function is missing from random_device.

There are two types of engines: simple and combined.

Simple engines

  • linear_congruential: A linear congruential generator, generating numbers by using this forumula:
  • x(i) = (A * x(i-1) + C) mod M
  • marsenne_twister: An implementation of the Marsenne twister. This generator keeps a value on W * (N-1) * R bits; each time a number needs to be generated, it extracts W bits. When all bits have been used it, twists the large value by shifting and mixing the bits so that it has a new set of bits to extract from.
  • subtract_with_carry: Generates numbers based on the following formula:
  • x(i) = (x(i - R) - x(i - S) - cy(i - 1)) mod M
    where
    cy(i) = x(i - S) - x(i - R) - cy(i - 1) < 0 ? 1 : 0
  • subtract_with_carry_01: Generates numbers based on the following formula:
  • x(i) = (x(i - R) - x(i - S) - cy(i - 1)) mod 1
    where
    cy(i) = if x(i - S) - x(i - R) - cy(i - 1) < 0 ? 2-W : 0
  • random_device: Generates random numbers by using an external device.

Combined engines

  • xor_combine: Generates numbers by using two engines; the numbers produced by these two wrapped engines are shifted and composed using this formula:
  • x(i) = (eng1(i) << S1) ^ (eng2(i) << S2)
  • discard_block: Uses another engine to produce numbers; some of these are discarded. The engine is parameterized with another engine, the length of the used sequence (P) and the length of the discarded sequence (R). The generated returns a new number at the first R calls. Then, it generates another P-R numbers that are discarded, and the process is repeated.

typedefs for these engines

  • minstd_rand0: Linear congruential generator
  • typedef linear_congruential<unsigned long, 16807, 0,
       2147483647>
       minstd_rand0;
    
  • minstd_rand: Linear congruential generator
  • typedef linear_congruential<unsigned long, 48271, 0,
       2147483647>
       minstd_rand;
    
  • mt19937: Marsenne twister
  • typedef mersenne_twister<unsigned long, 32, 624, 397, 31,
       0x9908b0df,
       11, 7, 0x9d2c5680, 15, 0xefc60000, 18> mt19937;
    
  • ranlux_base_01: Generator based on subtraction with carry
  • ranlux3 si ranlux4: Discarding generator based on subtraction with carry
  • typedef subtract_with_carry<unsigned long, 1 << 24,
       10, 24> _Ranbase;
    typedef discard_block<_Ranbase, 223, 24> ranlux3;
    typedef discard_block<_Ranbase, 389, 24> ranlux4;
    
  • ranlux3_01 si ranlux4_01: Discarding generator based on subtraction with carry
  • typedef subtract_with_carry_01<float, 24, 10, 24>
       _Ranbase_01;
    typedef discard_block<_Ranbase_01, 223, 24> ranlux3_01;
    typedef discard_block<_Ranbase_01, 389, 24> ranlux4_01;
    
  • ranlux_64_01: Generator based on subtraction with carry
  • typedef subtract_with_carry_01<double, 48, 5, 12>
       ranlux64_base_01;
    

Distributions

In TR1 terms, a distribution is a class that transforms a stream of uniformly distributed random numbers (generated by an engine) into a stream of numbers in a particular distribution. The random numbers produced by an engine are always uniformly distributed. To change the distribution of these numbers, you have to use a distribution class.

All distribution classes have the following methods:

  • reset(): Clears all cached values that were previously generated by an engine
  • operator(): Returns values (one at a time) within a specific distribution (numbers generated by an engine)

TR1 provides the following distribution classes:

How to Use Engines and Distributions

The simplest way to generate random numbers is to use a generator. The following example uses a linear congruential generator to generate 10 numbers, uniformly distributed.

// linear congruential generator
std::tr1::minstd_rand gen;

// initialize the generator
gen.seed((unsigned int)time(NULL));

// generate the numbers
for(int i = 0; i < 10; ++i)
{
   std::cout << gen() << " ";
}
std::cout << std::endl;

If the seeding is forgotten, the same sequence is generated each time you run the program:

48271 182605794 1291394886 1914720637 2078669041 407355683
   1105902161 854716505 564586691 1596680831

If you wanted to generate numbers in the interval [0, 9], you can apply the modulo 10 function on the generated numbers.

for(int i = 0; i < 10; ++i)
{
   std::cout << gen() % 10 << " ";
}

The same result, 10 numbers uniformly distributed between 0 and 9, can be generated by combining the generator with a uniform distribution.

// linear congrunetial generator
std::tr1::minstd_rand gen;

// uniform integer distribution
std::tr1::uniform_int<int> dist(0, 9);

// initialize the generator
gen.seed((unsigned int)time(NULL));

// generate the numbers
for(int i = 0; i < 10; ++i)
{
   std::cout << dist(gen) << " ";
}
std::cout << std::endl;

Another possibility is to associate a generator with a distribution using the variate_generator class.

// linear congrunetial generator
std::tr1::minstd_rand gen;

// uniform integer distribution
std::tr1::uniform_int<int> dist(0, 9);

// initialize the generator
gen.seed((unsigned int)time(NULL));

// associate a generator with a distribution
std::tr1::variate_generator<
   std::tr1::minstd_rand,
   std::tr1::uniform_int<int>> combgen(gen, dist);

// generate numbers
for(int i = 0; i < 10; ++i)
{
   std::cout << combgen() << " ";
}
std::cout << std::endl;

If seeding had been done after defining combgen, the sequence would have been the same with each run.

// associate a generator with a distribution
std::tr1::variate_generator<
   std::tr1::minstd_rand,
   std::tr1::uniform_int<int>> combgen(gen, dist);

// initialize the generator
gen.seed((unsigned int)time(NULL));
0 6 8 9 1 5 3 2 7 0

The reason for this is that a copy of the (uninitialized) generator is made when instantiating combgen. If the type of the generator was a reference type, initialization could have been done after.

// associate a generator with a distribution
std::tr1::variate_generator<
   std::tr1::minstd_rand&,
   std::tr1::uniform_int<int>> combgen(gen, dist);

// initialize the generator
gen.seed((unsigned int)time(NULL));

The same thing happens if you use a pointer type:

// associate a generator with a distribution
std::tr1::variate_generator<
   std::tr1::minstd_rand*,
   std::tr1::uniform_int<int>> combgen(&gen, dist);

// initialize the generator
gen.seed((unsigned int)time(NULL));

The next sample shows how to use a combined generator. This generator is initialized not with a value, but with a random number produced by another generator.

// engines
std::tr1::minstd_rand gen1;
std::tr1::mt19937 gen2;
std::tr1::linear_congruential<unsigned long, 33614, 0,
   2147483647> seeder;

// initialize the seeder
seeder.seed((unsigned int)time(NULL));

// combined engine
std::tr1::xor_combine<
   std::tr1::minstd_rand,    // first engine
   // shifting value for the numbers from the first engine
   7,
   std::tr1::mt19937,        // second engine
   // shifting value for the numbers from the second engine
   13
   > xorgen(gen1, gen2);

// exponential distribution
std::tr1::exponential_distribution<float> expdist(2);

// initialize the combined generator
xorgen.seed(seeder);

// generate numbers
for(int i = 0; i < 10; ++i)
{
   std::cout << xorgen() << " ";
}
std::cout << std::endl;

Conclusions

With TR1, the standard C++ library becomes richer in the possibilities of generating random number generators. Engines and distributions can be combined to generate numbers to meet various requirements. Perhaps, in the future, MSDN also will be enriched with examples for their usage. In the meantime, hopefully this article provides a good introduction for that.



About the Author

Marius Bancila

Marius Bancila is a Microsoft MVP for VC++. He works as a software developer for a Norwegian-based company. He is mainly focused on building desktop applications with MFC and VC#. He keeps a blog at www.mariusbancila.ro/blog, focused on Windows programming. He is the co-founder of codexpert.ro, a community for Romanian C++/VC++ programmers.

Comments

  • beauty from clarisonic venerable

    Posted by iouwanzi on 06/06/2013 05:22am

    [url=http://www.miaclarisonicaustralia.org/clarisonic-pro]clarisonic pro[/url] N’importe quel moment une personne prise à la dernière mode en mode et beauté, vous réalisez vraiment que le faste et le glamour des années 20 ont tendance à être offerts. Pour sûr, hivernal sera donner stratégie vers grésillant chaud pin up en vous en fait toute cette métamorphose, vous pouvez compter sur n’importe quelle collection de ghd écarlate.Cette approche complètement nouveau petit format Styler Golden Classic ® réinventé simplement en changeant la couleur concernant la véritable redressage des disques et donc passer à travers du métal jaune pour vous à rouge foncé. [url=http://www.australiaclarisonic.com/]clarisonic brush[/url] Modèle d’organisation ghd fer des prix, qui sont eux-mêmes trouvés sur le marché, maintenant il ya beaucoup de gens qui ont pu être mieux. En collaboration avec une solution de développement plus ou moins à chaque fois pour la décoration céramique lisseur cheveux crépus GHD MK4 est fluorescent productivité du système de téléphone sans réponse merveille à cet univers lié à la décoration des cheveux bouclés.L’utilisation d’un intense curiosité particulière structure actuelle cheveux bouclés et la conception du temps et une couverture supplémentaire dans votre chemin équivalent à travers les cheveux crépus de votre client supporte le meilleur que fournissent habituellement la plupart de ces produits et de services pour les cheveux bouclés ainsi que les entreprises de complètement mentionner traitements phénoménales sont très efficaces avec leur défrisage sauvage. [url=http://www.australiaclarisonic.com/]clarisonic brush[/url] Souvent, vous pourriez certainement blâmer la médecine. straightner cheveux babyliss Pour être en mesure de bien déterminer qui sont les premiers hébergeurs sont le soutien cyberespace, vous avez vraiment besoin de prendre du temps, ce qui est malheureusement de vos services, pour explorer avec vous pour la recherche.

    Reply
  • GHD skønhed poster tendens til at være for at kunne lÃ¥se præcis hvad en stor designer er faktisk for dit tøj

    Posted by motherdhmm on 05/30/2013 01:00pm

    [url=http://www.buy-beatsdrdre.com/]beats by dre headphones[/url] På nuværende tidspunkt i Danmark, ghd fladjern stigende salg boom, men også fremkomsten af ??en række websteder, der sælger ghd glattejern der er en ægte ghd håret identifikation, og vi ghd glattejern online markedsføring, GHD glattejern klassificering klare design. Søg nemt og hurtigt, autentiske ghd håret overkommelig design-orienteret øverste håndtag design og et unikt serienummer til internt brug. Kan ses med de standard funktioner ghd glattejern, frem for alt, så du værd investeringen. [url=http://www.blog.cheapbeatsbydre.co.nz/beats-by-dre-headphones]beats by dre headphones[/url] Absolut forskning den faktiske visse udstyret interiør, at vælge et tage et kig på højre ind GHD merchandise siden den ideelle ægtefælle Hvis du overvejer blot om enhver type, der er tilknyttet barnet inden for sætninger involverer. GHD er definitivt næsten helt sikkert de særlige producerede leverandører, som vil præsentere korrekt værdige af tresses straightners med hinanden og hårtørrer. [url=http://www.blog.cheapbeatsbydre.co.nz/monster-headphone]monster beats headphone[/url] Hår er en kvindes identitet, Enhver kvinde håber alle, at gennem de forskellige stilarter til at ændre billedet, Face, at gøre sig smukkere, mere ungdommeligt, eller elegance, vil man være i stand til at opfylde alles idé om hår, Vi lærer sammen, hvordan til at vælge billige ghd glattejern? ghd glattejern, hvordan du bruger? Forberedelse.

    Reply
  • Lightweight perceptive – Nike Unshackled TR Right in shoot up 2013 3 series

    Posted by Tufffruntee on 04/22/2013 03:47am

    Nike Free TR Fit 3 unmistakable features is to exploit the new scheme: Nike Self-ruling 5 soles improved bending Striation; modern tractor imitate making training more focused when; lighter load, the permeability is stronger, and more smart shoe designs not only order shoes [url=http://northernroofing.co.uk/roofins.cfm]nike free run 3[/url] more comfortable wearing, barefoot training caress, but also more in fashion appearance. Nike Relieve TR Robust 3 provides excellent lateral perseverance, you can be suffering with the legs in the part during training. Diligent vamp majuscule letters breathable mesh, lower suds's one of a kind delineate can be [url=http://markwarren.org.uk/property-waet.cfm]air max 90 uk[/url] seen under the aegis it. Lightweight, ragged, thin foam material occupied past completely occasional seams, more limber, support is stronger. Lack more advance, factor of a training irritate, froth neck in more parts of the neediness in return give, bubble loose. Put to use twice say nothing moisture wicking fake materials, flat on your feet, help maintenance feet sear and comfortable. Phylite [url=http://northernroofing.co.uk/roofins.cfm]nike free run[/url] midsole offers lightweight shock unchanging, superior durability and stable outsole can do to greatly lower the total weight of the shoe. Qianzhang pods on the outsole and heel-shaped Grassland rubber enhances the shoe multi-directional drag on odd surfaces.

    Reply
  • Women's clothing from Distance features the latest styles and fashions that you are unblinking to melodic tooth

    Posted by carpitojx on 04/16/2013 01:23am

    We wanted to choose some in days of yore to highlight some of the talented shops [url=http://www.hollistercorfrance.fr]hollister france[/url] revealed there that coordinate supported CONFORM TO as a replacement after so long and are doing engaging things in their parts of the hinterlands or the enchant俥 ' [url=http://www.abercrombiesfrancevparise.fr]abercrombie france[/url]. There are renowned maverick retailers into public observe there, innumerable of which are cultivating trends in the forefront they trounce the larger market. It's so rush to go to our ticket and our retailers to [url=http://www.airjordanfrpaschere.fr]jordan[/url] constantly be evolving. We all include so much taste representing the assiduity we lucubrate away in and the reciprocal target of pushing the sedulousness forward. Sufficiency jibba jabba, today's article is on MUST STOCK CO in Richmond, [url=http://www.abercrombieufrancersoldes.fr]abercrombie[/url] VA. The Nakate Bash also works to generate artisans in country areas [url=http://www.airjordanspasuchere.fr]air jordan[/url] of Uganda that we appreciate as occasion finished untapped or undervalued. They resist in providing income into women that are struggling to put championing themselves [url=http://www.hollisterfrancevmagesin.fr]hollister[/url] and, with a view the duration of bounteous of them, the families that are relying on their income. The predict also adheres to objective barter principles and environmentally friendly practices [url=http://www.abercrombievandfitchuks.co.uk]abercrombie[/url] including maximizing the pour down the drain of sore materials from sustainably managed sources, buying locally where practicable and encouraging our artisans to succeed in environments of their choosing – which are all together after tempo in the disclose [url=http://www.monclerfrancermagasinsfr.fr]moncler[/url] air. But in November, we each had a dialect mayhap to control a step assist and look [url=http://www.airjordanzchaussuren.com]air jordan[/url] at things from a far apart from perspective. We had been in so abstruse, plugging away, racing on to the next gismo that we hadn’t bewitched the plan to look up [url=http://www.michaelukorsua.com]michael kors outlet[/url] and summon inquire ourselves what we definitely wanted.We’ve dedicated two and a half years to creating a brand and a commodity that exceeded our (wildest) expectations. We’ve lettered more than we at all times soup噊n [url=http://www.hollisterucoboutiquer.fr]hollister[/url] possible. We’ve met awe-inspiring people and made expensive connections. We’ve discovered a passion championing something we didn’t withdraw we had.But with all of this advance, we’ve recently realized that revolvement threads [url=http://patrimoine.agglo-troyes.fr/BAM/louboutinpascher.html]louboutin pas cher[/url] is no longer something we desire after, or sensation we pressure, to proceed with what we were meant to do.

    Reply
  • What is TR1?

    Posted by inbugable on 07/11/2008 11:59pm

    Please mention what TR1 is, and how to get it.

    • Re: What is TR1

      Posted by cilu on 07/28/2008 06:10am

      I explain what this is in the first article of the series. TR1 stands for Technical Report 1, which specifies the new additions to the C++ standard. Microsoft provides an early implementation for these new things and they are available with the Visual C++ Feature Pack (http://www.microsoft.com/downloads/details.aspx?FamilyId=D466226B-8DAB-445F-A7B4-448B326C48E7&displaylang=en).

      Reply
    Reply
Leave a Comment
  • Your email address will not be published. All fields are required.

Top White Papers and Webcasts

  • Live Event Date: October 29, 2014 @ 11:00 a.m. ET / 8:00 a.m. PT Are you interested in building a cognitive application using the power of IBM Watson? Need a platform that provides speed and ease for rapidly deploying this application? Join Chris Madison, Watson Solution Architect, as he walks through the process of building a Watson powered application on IBM Bluemix. Chris will talk about the new Watson Services just released on IBM bluemix, but more importantly he will do a step by step cognitive …

  • Agile methodologies give development and test teams the ability to build software at a faster rate than ever before. Combining DevOps with hybrid cloud architectures give teams not just the principles, but also the technology necessary to achieve their goals. By combining hybrid cloud and DevOps: IT departments maintain control, visibility, and security Dev/test teams remain agile and collaborative Organizational barriers are broken down Innovation and automation can thrive Download this white paper to …

Most Popular Programming Stories

More for Developers

Latest Developer Headlines

RSS Feeds