C++ can get very irritating if all you want is a simple solution. Take random number generation for example. The <random> header was added to C++ to provide all kinds of random number generation. While it does cover any kind of random generation you can dream of, it makes writing a simple random generator super-hard! Unlike C or C#, where you can quickly generate random numbers with little code, in C++ it takes a lot of reading, pondering and lots of ugly-looking code.
<random>
The <random> header file provides many kinds of classes:
- Engine: It generates random numbers based on a certain algorithm. There are many engines defined in <random>. One example is linear_congruential_engine, which uses the algorithm that is typically used in the C rand() random number generator. A engine cannot be used alone, it should be attached to a distribution (see below).
- Predefined Engine: It is an engine created with some good-quality initial values. This saves a lot of the pain of coming up with values to initialize the engine. There are many predefined engines in <random>. For example, minstd_rand is pre-defined on the linear_congruential_engine.
- Distribution: It takes the output of an engine and shapes it to fit a certain distribution. An example is uniform_real_distribution, which creates an uniform distribution of real numbers. A distribution needs an engine to provide it with random number input.
- Variate Generator: variate_generator is a wrapper to combine an engine (or predefined engine) with a distribution, to create a custom random number generator.
Simple Random Number Generation
Here is a simple random number generator that produces random float values. It uses the variate_generator to wrap a minstd_rand engine and uniform_real_distribution.
#include <random> using namespace std; typedef minstd_rand Engine; typedef uniform_real_distribution<float> Distribution; typedef variate_generator<Engine, Distribution> Generator; Generator gen( Engine(9999), Distribution( 10, 100 ) ); cout << "Random value: " << gen() << endl;
The minstd_rand engine requires a seed, here we seed it with 9999. We also provide the uniform_real_distribution an output range of [10.0,100.0).
Simple Random Generator Class
If all I want is to generate some random number simply and quickly, the C++ <random> looks truly foreboding!
Here is a simple random number generator class that wraps up the complexity to provide a simple interface:
#include <random>
using namespace std;
class MyRandom
{
private:
// Types
typedef minstd_rand Engine;
typedef uniform_real_distribution<float> Distribution;
typedef variate_generator<Engine, Distribution> Generator;
// To hold the generator
Generator* _gen;
public:
MyRandom( int seed, float minVal, float maxVal )
{
_gen = new Generator( Engine( seed ), Distribution( minVal, maxVal ) );
}
~MyRandom()
{
delete _gen;
}
float next()
{
return (*_gen)();
}
};
The above class interface is influenced by C# Random, which is how simple and accessible C++ should have been! Writing code using the above class is easy:
const int seed = 9999; const float minVal = 10; const float maxVal = 100; MyRandom myRand( seed, minVal, maxVal ); cout << "Random value: " << myRand.next() << endl;
I hope this post made digesting <random> a wee bit easier!
Nice little wrap up, but why are manually managing your memory?
Since is a C++11 header anyways just use std::unique_ptr instead of new/delete!
Since the random header*
MyGateNet: The post was written 2 years ago when I was not very aware of unique_ptr. Thanks for the pointer
Oh, yeah I notice the date only after my comment.
Also the code doesn’t work with C++11 anymore, since there is no ‘variate_generator’, but it was still helpful after all.