I have been programming in Java for three years, and have been using Math.random() to get a random number. I'm fairly new to C++, and I was wondering if there was equivalent to that but in C++? A specific function or method that I could use? Also include an explanation. Thanks so much!
C++ provides a fairly nice random number library, <random>, but it doesn't yet have the sort of dead simple API beginners generally want. It's easy to produce such an API, as I show below, and hopefully some such API will be included at some point.
The C++ API splits random number generation into two parts, sources of 'randomness', and machinery for turning randomness into numbers with specific distributions. Many basic uses of random numbers don't particularly care how good (or fast, or small) the source of 'randomness' is, and they only need 'uniform' distributions. So the typically recommended source of randomness is the "Mersenne Twister" engine. You create one of these and seed it like so:
#include <random>
int main() {
std::mt19937 eng{42};
}
Now eng is an object that can be passed around and used as a source for random bits. It's a value-type so you can make copies of it, assign to it, etc. like a normal value. In terms of thread safety, accessing this value is like accessing any other, so if you need multiple threads you should either put an engine on each thread or use mutual exclusion.
To turn data from an engine into random values, use a distribution object. Typical uses need 'uniform' distributions, so for integral values use std::uniform_int_distribution<int>.
std::uniform_int_distribution<int> dice{1, 6};
A distribution object is a function object, and you get values from it by calling it and passing it the source of randomness it will use:
auto die_roll = dice(eng);
One thing to keep in mind is that the math for producing random values should be encapsulated inside a distribution object. If you find yourself doing some kind of transformation on the results then you probably should be using a different distribution. Don't do things like dist(eng) % 10 or dist(eng) / 6.0 + 10.0. There are several other distributions provided in the library, including ones for producing floating point values with various distributions.
Here's a pretty easy way to wrap the <random> functionality for simple usage:
#include <iostream>
#include <random>
std::mt19937 seeded_eng() {
std::random_device r;
std::seed_seq seed{r(), r(), r(), r(), r(), r(), r(), r()};
return std::mt19937(seed);
}
class Random {
std::mt19937 eng = seeded_eng();
public:
auto operator()(int a, int b) {
std::uniform_int_distribution<int> dist(a, b);
return dist(eng);
}
};
int main() {
Random random;
for (int i = 0; i < 10; ++i) {
std::cout << "Dice: " << random(1, 6) << " " << random(1, 6) << '\n';
}
}
#include <iostream>
#include <ctime>
int main()
{
srand((unsigned int) time (NULL)); //activates the generator
//...
int a = rand()%10; //gives a random from 0 to 9
double r = ((double) rand() / (RAND_MAX)); //gives a random from 0 to 1
int max, min;
//...
int c = (rand()%(max - min)) + min; //gives a random from min to max
//...
return 0;
}
These ways are the simpliest.
Sometimes it means "the best", sometimes - not.
1.srand((unsigned) time(0)) will make sure that everytime you run your program that the rand() function will get a new seed causing it to produce a different or "random" output. Without stand((unsigned) time(0)), the rand() will produce the same output.
2.int Number, is used to store the random number that is being generated by the rand() function. The rand() % 27 will give you numbers 0-26.
#include <iostream>
#include <ctime>
int main()
{
srand((unsigned)time(0))
int Number = ((rand() % 27));
cout << Number << endl;
return 0;
}
Here is a simple solution. The function random is overloaded. One instance is used to acquire a random number generator for integers. Another instance is used to acquire a random number generator for doubles. After you have these two functions, applications becomes rather trivial as can be observed in the main function.
#include <algorithm>
#include <functional>
#include <iostream>
#include <iterator>
#include <numeric>
#include <ostream>
#include <random>
// Single global engine, a better version of std::rand
std::mt19937 engine{ std::random_device()() };
// Returns a generator producing uniform random integers in the closed range [a, b]
std::function<int()> random(int a, int b)
{
auto dist = std::uniform_int_distribution<>(a, b);
return std::bind(dist, std::ref(engine));
}
// Returns a generator producing uniform random doubles in the half-open range [x, y)
std::function<double()> random(double x, double y)
{
auto dist = std::uniform_real_distribution<>(x, y);
return std::bind(dist, std::ref(engine));
}
int main()
{
const auto no_iterations = int{ 12 };
auto dice = random(1, 6);
// Roll the dice a few times and observe the outcome
std::generate_n(std::ostream_iterator<int>(std::cout, " "),
no_iterations, dice);
std::cout << std::endl;
// U is a uniform random variable on the unit interval [0, 1]
auto U = random(0.0, 1.0);
// Generate some observations
std::vector<double> observations;
std::generate_n(std::back_inserter(observations), no_iterations, U);
// Calculate the mean of the observations
auto sum = std::accumulate(observations.cbegin(), observations.cend(), 0.0);
auto mean = sum / no_iterations;
std::cout << "The mean is " << mean << std::endl;
return 0;
}
Related
How do I generate a random double in C++ that uses exponential distribution, and a mean with or without a standard deviation? For example, I want to make a simulation where there is a queue with processes in it. Knowing that the mean run time of the processes is 60 seconds, how can I generate random run time values for each process?
When you mention mean and standard deviation, I think what you're looking for is normal distribution, not exponential distribution.
You may be interested to take a look at std::normal_distribution.
If you look at the linked documentation, you'll find an example of how to use it:
#include <iostream>
#include <iomanip>
#include <string>
#include <map>
#include <random>
#include <cmath>
int main()
{
std::random_device rd{};
std::mt19937 gen{rd()};
// values near the mean are the most likely
// standard deviation affects the dispersion of generated values from the mean
std::normal_distribution<> d{5,2};
std::map<int, int> hist{};
for(int n=0; n<10000; ++n) {
++hist[std::round(d(gen))];
}
for(auto p : hist) {
std::cout << std::setw(2)
<< p.first << ' ' << std::string(p.second/200, '*') << '\n';
}
}
From cppreference.com
Exponential distribution is not the same thing, and it takes a single parameter, the rate of events, called lambda.
For future readers looking for exponential distribution (since the question explicitly mention it in the title), the standard implements the exponential distribution through std::exponential_distribution.
The C++ Standard Library provides std::exponential_distribution(1), which
Produces random non-negative floating-point values x, distributed according to probability density function:
P(x|λ) = λe-λx
Given such a distribution(2),
The mean or expected value of an exponentially distributed random variable X with rate parameter λ is given by
E[X] = 1 / λ
So that you can derive the parameter lambda from the required mean:
#include <iostream>
#include <random>
int main()
{
std::random_device rd;
std::seed_seq ss{ rd(), rd(), rd() };
std::mt19937 gen{ss};
constexpr double mean{ 60 };
constexpr double lambda{ 1.0 / mean };
std::exponential_distribution<> d(lambda);
for( int n=0; n<10; ++n ) {
std::cout << d(gen) << '\n';
}
}
https://en.cppreference.com/w/cpp/numeric/random/exponential_distribution
https://en.wikipedia.org/wiki/Exponential_distribution
I want to generate a set of unit vectors (for any arbitrary dimension), which are evenly distributed across all directions. For this I generate normally distributed numbers for each vector component and scale the result by the inverse of the magnitude.
My question: Can I use a single std::default_random_engine to generate numbers for all components of my vector or does every component require its own engine?
Afaik, each component needs to be Gaussian-distributed independently for the math to work out and I cannot assess the difference between the two scenarios. Here's a MWE with a single RNG (allocation and normalization of vectors is omitted here).
std::vector<std::vector<double>> GenerateUnitVecs(size_t dimension, size_t count)
{
std::vector<std::vector<double>> result;
/* Set up a _single_ RNG */
size_t seed = GetSeed(); // system_clock
std::default_random_engine gen(seed);
std::normal_distribution<double> distribution(0.0, 1.0);
/* Generate _multiple_ (independent?) distributions */
for(size_t ii = 0; ii < count; ++ii){
std::vector<double> vec;
for(size_t comp = 0; comp < dimension; ++comp)
vec.push_back(distribution(gen)); // <-- random number goes here
result.push_back(vec);
}
return result;
}
Thank you.
The OP asked:
My question: Can I use a single std::default_random_engine to generate numbers for all components of my vector or does every component require its own engine?
I would suggest as others have stated in the comments about not using std::default_random_engine and instead use std::random_device or std::chrono::high_resolution_clock
To use random_device for a normal distribution or Gaussian it is quite simple:
#include <iostream>
#include <iomanip>
#include <string>
#include <map>
#include <random>
#include <cmath>
int main() {
std::random_device rd{};
std::mt19937 gen{ rd() };
// values near the mean are the most likely
// standard deviation affects the dispersion of generated values from the mean
std::normal_distribution<> d{5,2};
std::map<int, int> hist{};
for ( int n=0; n<10000; ++n ) {
++hist[std::round(d(gen))];
}
for ( auto p : hist ) {
std::cout << std::setw(2)
<< p.first << ' ' << std::string(p.second/200, '*' ) << '\n';
}
}
To use std::chrono::high_resolution_clock: there is a little more work but just as easy.
#include <iostream>
#include <iomanip>
#include <string>
#include <map>
#include <random>
#include <cmath>
#include <limits>
#include <chrono>
class ChronoClock {
public:
using Clock = std::conditional_t<std::chrono::high_resolution_clock::is_steady,
std::chrono::high_resolution_clock,
std::chrono::steady_clock>;
static unsigned int getTimeNow() {
unsigned int now = static_cast<unsigned int>(Clock::now().time_since_epoch().count());
return now;
}
};
int main() {
/*static*/ std::mt19937 gen{}; // Can be either static or not.
gen.seed( ChronoClock::getTimeNow() );
// values near the mean are the most likely
// standard deviation affects the dispersion of generated values from the mean
std::normal_distribution<> d{5,2};
std::map<int, int> hist{};
for ( int n=0; n<10000; ++n ) {
++hist[std::round(d(gen))];
}
for ( auto p : hist ) {
std::cout << std::setw(2)
<< p.first << ' ' << std::string(p.second/200, '*' ) << '\n';
}
}
As you can see from the examples above where these are shown here from cppreference.comthere is a single engine, single seed, and a single distribution, that it is generating random numbers or sets of random numbers with a single engine.
EDIT - Additionally you can use a class that I've written as a wrapper class for random engines and random distributions. You can refer to this answer of mine here.
I am assuming you are not generating random numbers in parallel. Then theoretically, there is no problem with generating random independent Gaussian vectors with one engine.
Each call to std::normal_distribution's () operator gives you a random real-valued number following specified Gaussian distribution. Successive calls of () operator give you independent samples. The implementation in gcc (my version: 4.8) uses the Marsaglia Polar method for standard normal random number generation. You can read this Wikipedia page for more detail.
However, for rigorous scientific research that demands high quality randomness and a huge amount of random samples, I would recommend using the Mersenne-Twister engine (mt19937 32-bit or 64-bit) instead of the default engine, since it is based on a well-established method, has long period and performs well on statistical random tests.
Q: How do I generate (many) uniformly distributed integers from a-priory unknown ranges? What is the prefered way in terms of performance (milions of generated numbers)?
Context: In my app I have to generate many pseudo random numbers in many places. I use singleton pattern for the generator to maintain reproducibility of the app's run. Distribution is always uniform in my case, but the problem is that there are far too many possible ranges to pre-made the distribution object in C++11 style.
What I tried: There are two obvious solutions to this, first is to have one-time distribution objects and second is to use modulo to transform random number from widest possible range to the desired one. But somehow i doubt these are best possible :)
#include <random>
#include <iostream>
#include "limits.h"
using namespace std;
mt19937 mt;
uniform_int_distribution<int> * fixedDist;
uniform_int_distribution<int> * variableDist;
// this version creates and delete dist after just one use
int getIntFromRange1(int from, int to){
variableDist = new uniform_int_distribution<int>(from,to);
int num = (*variableDist)(mt);
delete variableDist;
return num;
}
// this version contains modulo
int getIntFromRange2(int from, int to){
int num = (*fixedDist)(mt);
int diff = to - from;
num = num % diff;
return num + from;
}
int main(){
mt.seed(123456);
fixedDist= new uniform_int_distribution<int>(0,INT_MAX)
int a = getIntFromRange1(1,10); // 1 and 10 are just for illustration
int b = getIntFromRange2(1,10); // can change freely
cout << "a: " << a << endl; // a: 6
cout << "b: " << b << endl; // b: 9
getchar();
}
Duplicate question
Vary range of uniform_int_distribution
I would do
int getIntFromRange1(int from, int to){
std::uniform_int_distribution<int> dist(from, to);
return dist(mt);
}
I would do as in Jarod42's answer: distribution objects should be lightweight, so constructing a new distribution when you need a random number is simple and fast (it's the random engine that is expensive).
However you can also consider this implementation:
inline int get_int_from_range(int from, int to)
{
using distribution_type = std::uniform_int_distribution<int>;
using param_type = typename distribution_type::param_type;
thread_local distribution_type dist;
return dist(mt, param_type(from, to));
}
The rationale is that there could be distributions that need to store values/states.
This isn't probably the case for integers and uniform distribution, but it's interesting that in N4316 - std::rand replacement the proposed implementation uses this technique.
For my program, I needed so far to draw one random value in [0..k[ from time to time, and using C++11 <random> features works really well. My current code is something like
class Random
{
public:
Random() : rng( rd() ) { }
inline int getRandNum( int limit ) { return ( numbers(rng) % limit ); }
private:
std::random_device rd;
std::mt19937 rng;
std::uniform_int_distribution<int> numbers;
};
Now, I need to draw in a row n different values in [0..k[. I was looking for something in <random> allowing that, but either I am not able to find it, or such a thing does not exist yet. Is there a clever, more elegant way to proceed than calling my getRandNum function and repeat until I get n different values?
EDIT: to give an idea, in my program k is some thousands and n some tens.
This solution is not C++ specific but can be easily implemented in any language.
What you want is essentially shuffle numbers 0 to k and pick the first n numbers, where n <= k.
This can be done using a reservoir sampling algorithm. See this wikipedia link for the pseudocode.
Note that it is possible to get the n numbers without storing all k numbers and shuffling them. That is, it is possible to just use O(n) space, where n is the number of random numbers you wish to obtain, instead of O(k). The time complexity for this algorithm is O(k), if we assume generating the random number takes O(1) time.
If k is several thousands and n is tens, then a permutation generation is really not the best choise. But calling getRandNum is not what you want too, because it can return the same value several times.
One option is to generate random sequence all at once, checking that the numbers don't repeat. The easiest (and may be even the most efficient) way to achieve this is to use a set.
Like so:
#include <vector>
#include <set>
#include <iostream>
#include <random>
class Random
{
public:
Random() : rng( rd() ) { }
inline int getRandNum( int limit ) { return ( numbers(rng) % limit ); }
std::set<int> getRandSequence(int limit, int n);
private:
std::random_device rd;
std::mt19937 rng;
std::uniform_int_distribution<int> numbers;
};
std::set<int> Random::getRandSequence(int limit, int n)
{
std::set<int> generatedSequence;
while (generatedSequence.size() < n) //size() for set is O(1) if I'm not mistaken
generatedSequence.insert(getRandNum(limit));
return generatedSequence;
}
int main()
{
Random r;
auto sequence = r.getRandSequence(1000, 10);
std::cout << "Seq;uence: " << std::endl;
for (int number : sequence)
std::cout << number << std::endl;
std::cout << "End" << std::endl;
return 0;
}
Ideone demo.
By the way, random_device creation is expensive, but uniform_int_distribution creation, as far as I remember, is not. So this might be even more efficient:
std::set<int> Random::getRandSequence(int limit, int n)
{
std::uniform_int_distribution<int> uiniformDistribution(0, limit);
std::set<int> generatedSequence;
while (generatedSequence.size() < n)
generatedSequence.insert(uiniformDistribution(rng));
return generatedSequence;
}
Besides, when you get a uniform distribution and then apply % limit to it, you don't get a uniform distribution anymore.
std::random_device rd; // obtain a random number from hardware
std::mt19937 eng(rd()); // seed the generator
std::uniform_int_distribution<> distr(0, 1500); // define the range
for(int a=0; a<limit; a++){
cout << distr(eng); //draw random nubmer
I'm hoping to find a way to fill an array with random floating point numbers. My array is size 50 and I'm hoping to fill this array with random float numbers from range 1-25. Here is what I have so far. I greatly appreciate any tips or answers anyone can offer. Thank you.
#include <iostream>
#include <ctime>
#include <cstdlib>
using namespace std;
int main()
{
float myArray[50];
for(int i = 1; i <= 25; i++)
{
srand(time(0));
myArray[i] = (rand()% 50 + 1);
cout << myArray[i] << endl;
system("Pause");
return 0;
}
}
If C++11 is an option I would use the random header and uniform_real_distribution:
#include <iostream>
#include <random>
int main()
{
std::random_device rd;
std::mt19937 e2(rd());
std::uniform_real_distribution<> dist(0, 25);
for (int n = 0; n < 50; ++n) {
std::cout << dist(e2) << ",";
}
std::cout << std::endl ;
}
Why do people say there is modulo bias when using a random number generator? explains why the naive use of modulus with rand() causes bias in the distribution and how to avoid it.
If C++11 is not an option, you can just use rand, dividing its result by the RAND_MAX constant casted to float to obtain a uniform distribution of floats in the range [0, 1]; then you can multiply it by 24 and add 1 to get your desired range:
myArray[i] = rand()/float(RAND_MAX)*24.f+1.f;
By the way, as other observed, move srand out of your loop - the RNG seed (normally) must be initialized only once.
(notice that dividing by RAND_MAX will give a distribution that includes the right extreme of your interval; if you want to exclude it, you should divide by e.g. RAND_MAX+1)
Of course, the resulting distribution is only as good as the original rand() distribution (both in randomness and in granularity); you will typically get a LCG and granularity of at least ~0.0007 (guaranteed by the standard, and what VC++ and other compilers actually provide). If you need better random numbers, you should follow the advices posted in the other answers (the default Mersenne twister generator in C++11 provides better randomness and a way bigger guaranteed range).
#include <random>
...
std::random_device rd;
std::mt19937 gen(rd());
std::uniform_real_distribution<float> dist(1.0f, 25.0f);
std::cout << dist(gen);
Each time the for loop iterates, it assigns one value in the array a random number. Since your array is of size 50, you want to iterate 50 times instead of 25 like you do now.
for(int i = 0; i < 50; i++)
Array bounds start at 0, so you can only access from array[0] to array[49].
To get a random number from 1-25, you want
myArray[i] = rand() % 25 + 1;
Also, do you want integers or floating point random numbers? Right now you are just getting integers, meaing 1, 2, 3, ... 25. If you want something like 2.45, 6.883, 23.999, etc. you need to do something different. See C++ random float number generation for the answer.
You probably don't want to pause every time you insert a number into the array. Move this after the for loop.
system("pause");
Also, if you return 0 inside the for loop, you will only assign one number before your program will exit. Move that to after the loop as well.
Use uniform_real. In the following program random float numbers between 1.0 and 2.0 are generated:
#include <random>
#include <iostream>
typedef std::ranlux64_base_01 Myeng;
typedef std::uniform_real<float> Myceng;
int main()
{
Myeng eng;
Myceng ceng(1.0, 2.0);
Myceng::input_type engval = eng();
std::cout << "a random value == " << ceng(eng) << std::endl;
std::cout << "a random value == " << ceng(eng) << std::endl;
std::cout << "a random value == " << ceng(eng) << std::endl;
return (0);
}