Search code examples
c++boostboost-random

How do I use Boost Random


I need to generate random number with Boost Random.

I tried to follow the general guide.

I extracted the files of the library. So if I want to use the classes and objectj of the library how I should do?

First I know including the library in the program. Then I have to compile the library and the program.cpp itself? (And both with the same compiler - I'm using g++).

I am using a virtual box of ubuntu. It is first time that I am using library so I really don't know.


Solution

  • the random number for my case must be double not just integer...

    So, you use a real number distribution.


    I'm not this kind of "getting started" is the best fit for StackOverflow, but I'll give you this quick hints:

    In your Ubuntu virtual box:

    sudo apt-get install libboost-all-dev
    mkdir -pv ~/myproject
    cd ~/myproject
    

    Create a file using your favourite editor. If you have none, gedit main.cpp or nano main.cpp is a start:

    #include <boost/random.hpp>
    #include <iostream>
    
    int main() {
        boost::random::mt19937 rng;                                        
        boost::random::uniform_real_distribution<double> gen(0.0, 1.0);
        for (int i = 0; i < 10; ++i) {
            std::cout << gen(rng) << "\n";
        }
    }
    

    Now compile it using

    g++ -O2 -Wall -Wextra -pedantic main.cpp -o demo
    

    The program is now ready to run: Live On Coliru

    ./demo
    

    Printing

    0.814724
    0.135477
    0.905792
    0.835009
    0.126987
    0.968868
    0.913376
    0.221034
    0.632359
    0.308167
    

    Seeding && Non-Header Only Libraries

    The above works because the Boost Random library is mostly header only. What if you wanted to use the random_device implementation to seed the random generator?

    Live On Coliru

    #include <boost/random.hpp>
    #include <boost/random/random_device.hpp>
    #include <iostream>
    
    int main() {
        boost::random::random_device seeder;
        boost::random::mt19937 rng(seeder());                                        
        boost::random::uniform_real_distribution<double> gen(0.0, 1.0);
        for (int i = 0; i < 10; ++i) {
            std::cout << gen(rng) << "\n";
        }
    }
    

    Now you'll have to link as well: Compiling with

    g++ -O2 -Wall -Wextra -pedantic main.cpp -o demo -lboost_random
    

    Now the output will be different each run.

    BONUS: Standard Library instead of Boost

    You don't need Boost here at all:

    Live On Coliru

    #include <random>
    #include <iostream>
    
    int main() {
        std::random_device seeder;
        std::mt19937 rng(seeder());                                        
        std::uniform_real_distribution<double> gen(0.0, 1.0);
        for (int i = 0; i < 10; ++i) {
            std::cout << gen(rng) << "\n";
        }
    }
    

    Compile with

    g++ -std=c++11 -O2 -Wall -Wextra -pedantic main.cpp -o demo
    

    And run it again with ./demo

    BONUS

    Showing a whole gamut of distributions that have mean=0 and stddev=1:

    Live On Coliru

    #include <random>
    #include <iostream>
    #include <iomanip>
    #include <chrono>
    #include <boost/serialization/array_wrapper.hpp>
    #include <boost/accumulators/accumulators.hpp>
    #include <boost/accumulators/statistics.hpp>
    
    namespace ba = boost::accumulators;
    using Accum = ba::accumulator_set<double, ba::stats<ba::tag::variance, ba::tag::mean> >;
    using Clock = std::chrono::high_resolution_clock;
    using namespace std::chrono_literals;
    
    static double identity(double d) { return d; }
    
    template <typename Prng, typename Dist, typename F = double(double), size_t N = (1ull << 22)>
    void test(Prng& rng, Dist dist, F f = &identity) {
        Accum accum;
    
        auto s = Clock::now();
        for (size_t i = 0; i<N; ++i)
            accum(f(dist(rng)));
    
        std::cout 
            << std::setw(34) << typeid(Dist).name() 
            << ":\t" << ba::mean(accum) 
            << " stddev: " << sqrt(ba::variance(accum)) 
            << " N=" << N 
            << " in " << ((Clock::now()-s)/1.s) << "s"
            << std::endl;
    }
    
    int main() {
        std::mt19937 rng(std::random_device{}());                                        
    
        auto shift = [](double shift) { return [=](double v) { return v + shift; }; };
        auto scale = [](double scale) { return [=](double v) { return v * scale; }; };
    
        std::cout << std::fixed << std::showpos;
        test(rng, std::uniform_real_distribution<double>(-sqrt(3), sqrt(3)));
        test(rng, std::weibull_distribution<double>(), shift(-1));
        test(rng, std::exponential_distribution<double>(), shift(-1));
        test(rng, std::normal_distribution<double>());
        test(rng, std::lognormal_distribution<double>(0, log(0.5)), shift(-exp(pow(log(0.5),2)/2)));
        test(rng, std::chi_squared_distribution<double>(0.5), shift(-0.5));
        {
            auto sigma = sqrt(6)/M_PI;
            static constexpr double ec = 0.57721566490153286060;
            test(rng, std::extreme_value_distribution<double>(-sigma*ec, sigma));
        }
        test(rng, std::fisher_f_distribution<double>(48, 8), shift(-(8.0/6.0)));
        test(rng, std::student_t_distribution<double>(4), scale(sqrt(0.5)));
        test(rng, std::student_t_distribution<double>(4), scale(sqrt(0.5)));
    }
    

    Prints

      St25uniform_real_distributionIdE: +0.000375 stddev: +1.000056 N=4194304 in +0.169681s
           St20weibull_distributionIdE: +0.001030 stddev: +1.000518 N=4194304 in +0.385036s
       St24exponential_distributionIdE: -0.000360 stddev: +1.000343 N=4194304 in +0.389443s
            St19normal_distributionIdE: -0.000133 stddev: +1.000330 N=4194304 in +0.390235s
         St22lognormal_distributionIdE: +0.000887 stddev: +1.000372 N=4194304 in +0.521975s
       St24chi_squared_distributionIdE: -0.000092 stddev: +0.999695 N=4194304 in +1.233835s
     St26extreme_value_distributionIdE: -0.000381 stddev: +1.000242 N=4194304 in +0.611973s
          St21fisher_f_distributionIdE: -0.000073 stddev: +1.001588 N=4194304 in +1.326189s
         St22student_t_distributionIdE: +0.000957 stddev: +0.998087 N=4194304 in +1.080468s
         St22student_t_distributionIdE: +0.000677 stddev: +0.998786 N=4194304 in +1.079066s