Search code examples
c++randombindgaussian

Gaussian draws in C++ using bind gives different result than drawing from distribution explicitly


I am studying the issue of generating Gaussian draws in C++. As the title says, I seem to get a different result from using bind instead of just drawing from the distribution. That is to say the following code

default_random_engine ran{1};
auto normal_draw = bind(normal_distribution<double>{0, 1}, ran);

for (int i = 0; i < 9; ++i)
    cout << normal_draw() << endl;

    cout << "new sequence" << endl;

for (int i = 0; i < 9; ++i)
    cout << normal_distribution<double>{0, 1}(ran) << endl;

generates the output

-1.40287 -0.549746 -1.04515 1.58275 -1.95939 0.257594 -0.315292 -1.50781 0.071343

new sequence

-1.40287 -1.04515 -1.95939 -0.315292 0.071343 -1.41555 0.631902 -0.903123 0.194431

I find this perplexing as I believed that both sequences would be the same. Note also that if one generates 18 draws using normal_draw() then the sequence comprising the last 9 draws is not equal to the second sequence above. So it seems like drawing directly from the distribution is using a different method than that implicit in bind(), which clearly cannot be the case.

Can someone please explain what I am missing?

thanks in advance!


Solution

  • You are instancing a temporary distribution object every loop iteration. This will create a new state every time. When you don't, they are the same (given the random generator is always initialized with the same state):

    #include <random>
    #include <iostream>
    #include <functional>
    
    int main()
    {
        std::default_random_engine ran1{1};
        auto normal_draw = std::bind(std::normal_distribution<double>{0, 1}, ran1);
    
        for (int i = 0; i < 9; ++i)
            std::cout << normal_draw() << ' ';
    
        std::cout << '\n';
    
        std::default_random_engine ran2{1};
        std::normal_distribution<double> norman{0, 1};
        for (int i = 0; i < 9; ++i)
            std::cout << norman(ran2) << ' ';
    }