I am trying to generate different random numbers following different distributions to conduct some experiments on them. I choose the boost library in c++ because I saw a large number of functions build in there. For example, in lognormal distribution, I followed this page https://www.boost.org/doc/libs/1_43_0/libs/math/doc/sf_and_dist/html/math_toolkit/dist/dist_ref/dists/lognormal_dist.html and some more. But I cannot understand how I can actually generate the random number. I tried
int main(){boost::math::lognormal_distribution<> myLognormal{0,8};cout << myLognormal() << endl; return 0;}
but its doing nothing but error.
You have had some helpful comments already. Let me tie it together into an example:
Using Standard Library (C++11 and up)
Live On Coliru
#include <random>
#include <iostream>
int main() {
std::mt19937 engine; // uniform random bit engine
// seed the URBG
std::random_device dev{};
engine.seed(dev());
// setup a distribution:
double mu = 1.0;
double sigma = 1.0;
std::lognormal_distribution<double> dist(mu, sigma);
for (int i = 1'000; i--;) {
std::cout << dist(engine) << "\n";
}
}
Plotting those numbers:
https://plotly.com/~sehe/27/
Using Boost Random
Same with Boost Random:
Live On Coliru
#include <boost/random.hpp>
#include <boost/random/random_device.hpp>
#include <iostream>
int main() {
boost::random::mt19937 engine; // uniform random bit engine
// seed the URBG
boost::random::random_device dev;
engine.seed(dev); // actually without call operator is better with boost
// setup a distribution:
double mu = 1.0;
double sigma = 1.0;
boost::random::lognormal_distribution<double> dist(mu, sigma);
for (int i = 1'000; i--;) {
std::cout << dist(engine) << "\n";
}
}
Note that you need to link the Boost Random library then.
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.
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;
}
I am working with C++11's random library, and I have a small program that generates a coordinate pair x, y on a circle with unit radius. Here is the simple multithreaded program
#include <iostream>
#include <fstream>
#include <random>
using namespace std;
int main()
{
const double PI = 3.1415;
double angle, radius, X, Y;
int i;
vector<double> finalPositionX, finalPositionY;
#pragma omp parallel
{
vector <double> positionX, positionY;
mt19937 engine(0);
uniform_real_distribution<> uniform(0, 1);
normal_distribution<double> normal(0, 1);
#pragma omp for private(angle, radius, X, Y)
for(i=0; i<1000000; ++i)
{
angle = uniform(engine)*2.0*PI;
radius = sqrt(uniform(engine));
X = radius*cos(angle);
Y = radius*sin(angle);
positionX.push_back(X);
positionY.push_back(Y);
}
#pragma omp barrier
#pragma omp critical
finalPositionX.insert(finalPositionX.end(), positionX.begin(), positionX.end());
finalPositionY.insert(finalPositionY.end(), positionY.begin(), positionY.end());
}
ofstream output_data("positions.txt", ios::out);
output_data.precision(9);
for(unsigned long long temp_var=0; temp_var<(unsigned long long)finalPositionX.size(); temp_var++)
{
output_data << finalPositionX[temp_var]
<< "\t\t\t\t"
<< finalPositionY[temp_var]
<< "\n";
}
output_data.close();
return 0;
}
Question: Many of the x-coordinates appear twice (same with y-coordinates). I don't understand this, since the period of the mt19937 is much longer than 1.000.000. Does anyone have an idea of what is wrong here?
Note: I get the same behavior when I don't multithread the application, so the problem is not related to wrong multithreading.
EDIT As pointed out in one of the answers, I shouldn't use the same seed for both threads - but that is an error I made when formulating this question, in my real program I seem the threads differently.
Using the core part of your code, I wrote this imperfect test but from what I can see the distribution is pretty uniform:
#include <iostream>
#include <fstream>
#include <random>
#include <map>
#include <iomanip>
using namespace std;
int main()
{
int i;
vector<double> finalPositionX, finalPositionY;
std::map<int, int> hist;
vector <double> positionX, positionY;
mt19937 engine(0);
uniform_real_distribution<> uniform(0, 1);
//normal_distribution<double> normal(0, 1);
for(i=0; i<1000000; ++i)
{
double rnum = uniform(engine);
++hist[std::round(1000*rnum)];
}
for (auto p : hist) {
std::cout << std::fixed << std::setprecision(1) << std::setw(2)
<< p.first << ' ' << std::string(p.second/200, '*') << '\n';
}
return 0;
}
and as others already said it is not unexpected to see some values repeated. For the normal distribution, I used the following modification to rnum and hist to test that and it looks good too:
double rnum = normal(engine);
++hist[std::round(10*rnum)];
As described in this article (and a later article by a Stack Overflow contributor), true randomness doesn't distribute perfectly.
Good randomness :
Bad randomness :
I really recommend reading the article, but to summarize it: a RNG has to be unpredictable, which implies that calling it 100 times must not perfectly fill a 10x10 grid.
First of all - just because you get the same number twice doesn't mean it isn't random. If you throw a dice six times, would you expect six different results? See birthday paradox. That being said - you are right that you shouldn't see too much repetition in this particular case.
I'm not familiar with "#pragma omp parallel", but my guess is you are spawning multiple threads that all seed the mt19937 with the same seed (0). You should use different seeds for all threads - e.g. the thread id.
Im currently having trouble generating random numbers between -32.768 and 32.768. It keeps giving me the same values but with a small change in the decimal field. ex : 27.xxx.
Heres my code, any help would be appreciated.
#include <iostream>
#include <ctime>
#include <cstdlib>
using namespace std;
int main()
{
srand( time(NULL) );
double r = (68.556*rand()/RAND_MAX - 32.768);
cout << r << endl;
return 0;
}
I should mention if you're using a C++11 compiler, you can use something like this, which is actually easier to read and harder to mess up:
#include <random>
#include <iostream>
#include <ctime>
int main()
{
//Type of random number distribution
std::uniform_real_distribution<double> dist(-32.768, 32.768); //(min, max)
//Mersenne Twister: Good quality random number generator
std::mt19937 rng;
//Initialize with non-deterministic seeds
rng.seed(std::random_device{}());
// generate 10 random numbers.
for (int i=0; i<10; i++)
{
std::cout << dist(rng) << std::endl;
}
return 0;
}
As bames53 pointed out, the above code can be made even shorter if you make full use of c++11:
#include <random>
#include <iostream>
#include <ctime>
#include <algorithm>
#include <iterator>
int main()
{
std::mt19937 rng;
std::uniform_real_distribution<double> dist(-32.768, 32.768); //(min, max)
rng.seed(std::random_device{}()); //non-deterministic seed
std::generate_n(
std::ostream_iterator<double>(std::cout, "\n"),
10,
[&]{ return dist(rng);} );
return 0;
}
Also, If you are not using c++ 11 you can use the following function instead:
double randDouble(double precision, double lowerBound, double upperBound) {
double random;
random = static_cast<double>(((rand()%(static_cast<int>(std::pow(10,precision)*(upperBound - lowerBound) + 1))) + lowerBound*std::pow(10,precision)))/std::pow(10,precision);
return random;
}
So, I think this is a typical case of "using time(NULL) isn't a great way of seeding random numbers for runs that start close together". There isn't that many bits that change in time(NULL) from one call to the next, so random numbers are fairly similar. This is not a new phenomena - if you google "my random numbers aren't very random", you'll find LOTS of this.
There are a few different solutions - getting a microsecond or nanosecond time would be the simplest choice - in Linux gettimeofday will give you a microsecond time as part of the struct.
It seams to be plainly obvious but some of the examples say otherwise... but i thought when you divide 1 int with another you always get an int? and you need to type cast each int to double/float before you divide them.
ie: double r = (68.556* (double)rand()/(double)RAND_MAX - 32.768);
also if you call srand() every time you call rand() you reset the seed which results in similar values returned every time instead of ''random'' ones.
I've added a for loop to your program:
#include <iostream>
#include <ctime>
#include <cstdlib>
using namespace std;
int main () {
srand(time (NULL));
for (int i = 0; i < 10; ++i) {
double r = ((68.556 * rand () / RAND_MAX) - 32.768);
cout << r << endl;
}
return 0;
}
Example output:
31.6779
-28.2096
31.5672
18.9916
-1.57149
-0.993889
-32.4737
24.6982
25.936
26.4152
It seems Okay to me. I've added the code on Ideone for you.
Here are four runs:
Run 1:
-29.0863
-22.3973
34.1034
-1.41155
-2.60232
-30.5257
31.9254
-17.0673
31.7522
28.227
Run 2:
-14.2872
-0.185124
-27.3674
8.12921
22.4611
-0.414546
-21.4944
-11.0871
4.87673
5.4545
Run 3:
-23.9083
-6.04738
-6.54314
30.1767
-16.2224
-19.4619
3.37444
9.28014
25.9318
-22.8807
Run 4:
25.1364
16.3011
0.596151
5.3953
-25.2851
10.7301
18.4541
-18.8511
-0.828694
22.8335
Perhaps you're not waiting at least a second between runs?