I learned to program in C# and have started to learn C++. I'm using the Visual Studio 2010 IDE. I am trying to generate random numbers with the distribution classes available in <random>. For example I tried doing the following:
#include <random>
std::normal_distribution<double> *normal = new normal_distribution<double>(0.0, 0.0);
std::knuth_b *engine = new knuth_b();
std::variate_generator<knuth_b, normal_distribution<double>> *rnd;
rnd = new variate_generator<knuth_b, normal_distribution<double>>(engine, normal);
The last line gives a compiler error:
IntelliSense: no instance of constructor "std::tr1::variate_generator<_Engine, _Distrib>::variate_generator [with _Engine=std::tr1::knuth_b, _Distrib=std::tr1::normal_distribution]" matches the argument list
My arguments look ok to me, what am I doing wrong? When the variate_generator class here is instantiated, which method do you call to get the next random number i.e. .NET's System.Random.Next()?
There is no variate_generator in C++0x, but std::bind works just as well. The following compiles and runs in GCC 4.5.2 and MSVC 2010 Express:
#include <random>
#include <functional>
#include <iostream>
int main()
{
std::normal_distribution<> normal(10.0, 3.0); // mean 10, sigma 3
std::random_device rd;
std::mt19937 engine(rd()); // knuth_b fails in MSVC2010, but compiles in GCC
std::function<double()> rnd = std::bind(normal, engine);
std::cout << rnd() << '\n';
std::cout << rnd() << '\n';
std::cout << rnd() << '\n';
std::cout << rnd() << '\n';
}
PS: avoid new when you can.
ALERT: Note that the above solution binds a copy of the engine, not a reference to the engine. Thus, if you also do:
std::function rnd2 = std::bind(normal, engine);
then the rnd object and the rnd2 object will produce the exact same sequence of random numbers.
Related
I am using this command line to compile my program.
clang++ -std=c++17 -O3 main.cpp -o main
I have started the compiler 20 minutes ago, and it is just hanging. I terminate the compiler, and try to compile it again and it is still hanging. If I use the exact same command line, but without the -O3 the compiler completes instantly, but with the -O3 it is hanging.
The code that it is compiling is relatively simple, without any errors. What is going on?
#include <ctime> // for time()
#include <cstdlib> // for srand(), rand(), size_t, EXIT_SUCCESS
#include <iostream>
#include <string>
#include <vector>
using std::cout;
using std::endl;
using std::string;
using std::vector;
int main()
{
vector<string> messages;
messages.push_back(string("“Blessed are those who are persecuted because of righteousness, for theirs is the kingdom of heaven.”"));
messages.push_back(string("“Let the little children come to me, and do not hinder them, for the kingdom of heaven belongs to such as these.”"));
/* Literally 10000 more quotes from the Bible. */
srand(time(NULL));
cout << messages[ rand() % messages.size() ] << endl;
return EXIT_SUCCESS;
}
What is going on?
If you want to keep all the strings in the program (instead of reading them from a file) I would replace the std::vector<std::string> with a const std::vector<std::string_view> or maybe even a const std::vector<const char*> and initialize it with all the strings:
#include <ctime> // for time()
#include <cstdlib> // for srand(), rand(), size_t, EXIT_SUCCESS
#include <iostream>
#include <string_view>
#include <vector>
int main() {
const std::vector<std::string_view> messages{
"“Blessed are those who are persecuted because of righteousness, for theirs is the kingdom of heaven.”",
"“Let the little children come to me, and do not hinder them, for the kingdom of heaven belongs to such as these.”",
/* Literally 10000 more quotes from the Bible. */
};
srand(time(NULL));
std::cout << messages[ rand() % messages.size() ] << '\n';
}
I wasn't patient enough to wait for the compiler to finish compiling your original code. The above compiled in ~1 second.
Note: There's a <random> header which gives you access to much better pseudo random number generation than rand(). You should look into using that instead. The end of your program would look like something like this using that:
std::mt19937 prng(std::random_device{}());
std::uniform_int_distribution<std::size_t> dist(0, messages.size() - 1);
std::cout << messages[ dist(prng) ] << '\n';
This question already has answers here:
Generating a random integer from a range
(14 answers)
Closed 9 years ago.
I'm generating random numbers in C++11. When I run my code
using namespace std;
static std::mt19937_64 rng;
int main() {
rng.seed(11);
std::cout << rng() << std::endl;
}
It returns random numbers. However, I would like to restrict this to a range of numbers, say 1-1000. How would I do this, using the new <random> file/library introduced in C++11?
Use std::uniform_int_distribution from <random>.
Example:
#include <random>
#include <iostream>
int main()
{
std::random_device rd;
std::mt19937 gen(rd());
std::uniform_int_distribution<int> dis(1, 1000);
std::cout << dis(gen) << '\n';
}
The <random> header includes a lot of other distributions that you can use. You can check it out here
I am working on a server with GCC version 4.4.7, and I am forced to work with this version unfortunately. I want to make use of the <random> library of C++0x, but I read here that in this version uniform_real_distribution is called uniform_real. When I try to call this function and normal_distribution, I don't get useful output. See this example:
#include <random>
#include <iostream>
using namespace std;
int main()
{
typedef std::mt19937 Engine;
typedef std::uniform_real<double> Dis1;
typedef std::normal_distribution<double> Dis2;
Engine eng(0);
Dis1 dis1(0, 1);
cout << dis1(eng) << endl; //OUTPUTS 3.49921e+09
Dis2 dis2(0, 1);
cout << dis2(eng) << endl; //STALLS, NO OUTPUT
return 0;
}
I compile with g++44 -std=c++0x main.cpp and I have shown what output I get. What is the issue here?
C++11 support in gcc 4.4 is rather sparse.
The release notes for gcc 4.5 include
Improved experimental support for the upcoming ISO C++ standard,
C++0x
specifically mentioning <random>.
I have been playing with Boost.Random for a day now, and while boost::uniform_int_distribution<> works well, I am having trouble with boost::exponential_distribution<>.
A simple program is worth a thousand words:
#include <iostream>
#include <boost/random/mersenne_twister.hpp>
#include <boost/random/exponential_distribution.hpp>
int main() {
boost::mt19937 gen;
boost::exponential_distribution<> dis;
std::cout << dis(gen) << "\n";
return 0;
}
Compiled with Clang 3.0, using Boost 1.39.1 (no, I cannot upgrade Boost).
The output is invariably the same: nan.
I could not find any reported issue so I guess it's me not using the library correctly... Any clue would be appreciated.
Given a random number r, uniformly distributed on [0,1), -log(r) is distributed on (0,infinity) with the distribution exp(-x).
The former is boost::uniform_01().
If you need a distribution p exp(-px), then it's -(1/p)log(r).
In both cases here log(x) is a natural log (base e).
UPD: Using boost::variate_generator seems to work for me (boost 1.43):
#include <iostream>
#include<boost/random.hpp>
int main() {
boost::mt19937 rng(11u);
boost::variate_generator< boost::mt19937&, boost::exponential_distribution<> > rndm(rng, boost::exponential_distribution<>()) ;
std::cout<<rndm()<<"\n";
}
I did not check the distribution though.
I would like to know if in C++ standard libraries there is any gaussian distribution number generator, or if you have any code snippet to pass.
Thanks in advance.
The standard library does not. Boost.Random does, however. I'd use that if I were you.
C++ Technical Report 1 adds support for random number generation. So if you're using a relatively recent compiler (visual c++ 2008 GCC 4.3), chances are that it is available out of the box.
See here for sample usage of std::tr1::normal_distribution (and many more).
The GNU Scientific Libraries has this feature. GSL - Gaussian Distribution
The answer to this question changes with C++11 which has the random header which includes std::normal_distribution. Walter Brown's paper N3551, Random Number Generation in C++11 is probably one of the better introductions to this library.
The following code demonstrates how to use this header (see it live):
#include <iostream>
#include <iomanip>
#include <map>
#include <random>
int main()
{
std::random_device rd;
std::mt19937 e2(rd());
std::normal_distribution<> dist(2, 2);
std::map<int, int> hist;
for (int n = 0; n < 10000; ++n) {
++hist[std::floor(dist(e2))];
}
for (auto p : hist) {
std::cout << std::fixed << std::setprecision(1) << std::setw(2)
<< p.first << ' ' << std::string(p.second/200, '*') << '\n';
}
}
I provide a more general set of examples to random number generation in C++11 in my answer to C++ random float number generation with an example in Boost and using rand() as well.