C++11: How to set seed using

前端 未结 2 524
醉话见心
醉话见心 2020-12-01 11:11

I am exercising the random library, new to C++11. I wrote the following minimal program:

#include 
#include 
using namespace st         


        
2条回答
  •  死守一世寂寞
    2020-12-01 11:26

    #include 
    #include 
    
    using namespace std;
    
    int main() {
        std::random_device r;                                       // 1
        std::seed_seq seed{r(), r(), r(), r(), r(), r(), r(), r()}; // 2
        std::mt19937 eng(seed);                                     // 3
    
        uniform_real_distribution urd(0, 1);
    
        cout << "Uniform [0, 1): " << urd(eng);
    }
    

    In order to get unpredictable results from a pseudo-random number generator we need a source of unpredictable seed data. On 1 we create a std::random_device for this purpose. On 2 we use a std::seed_seq to combine several values produced by random_device into a form suitable for seeding a pseudo-random number generator. The more unpredictable data that is fed into the seed_seq, the less predictable the results of the seeded engine will be. On 3 we create a random number engine using the seed_seq to seed the engine's initial state.

    A seed_seq can be used to initialize multiple random number engines; seed_seq will produce the same seed data each time it is used.

    Note: Not all implemenations provide a source of non-deterministic data. Check your implementation's documentation for std::random_device.


    If your platform does not provide a non-deterministic random_device then some other sources can be used for seeding. The article Simple Portable C++ Seed Entropy suggests a number of alternative sources:

    • A high resolution clock such as std::chrono::high_resolution_clock (time() typically has a resolution of one second which generally too low)
    • Memory configuration which on modern OSs varies due to address space layout randomization (ASLR)
    • CPU counters or random number generators. C++ does not provide standardized access to these so I won't use them.
    • thread id
    • A simple counter (which only matters if you seed more than once)

    For example:

    #include 
    #include 
    #include 
    #include 
    #include 
    
    using namespace std;
    
    // we only use the address of this function
    static void seed_function() {}
    
    int main() {
        // Variables used in seeding
        static long long seed_counter = 0;
        int var;
        void *x = std::malloc(sizeof(int));
        free(x);
    
        std::seed_seq seed{
            // Time
            static_cast(std::chrono::high_resolution_clock::now()
                                       .time_since_epoch()
                                       .count()),
            // ASLR
            static_cast(reinterpret_cast(&seed_counter)),
            static_cast(reinterpret_cast(&var)),
            static_cast(reinterpret_cast(x)),
            static_cast(reinterpret_cast(&seed_function)),
            static_cast(reinterpret_cast(&_Exit)),
            // Thread id
            static_cast(
                std::hash()(std::this_thread::get_id())),
            // counter
            ++seed_counter};
    
        std::mt19937 eng(seed);
    
        uniform_real_distribution urd(0, 1);
    
        cout << "Uniform [0, 1): " << urd(eng);
    }
    

提交回复
热议问题