How to get current seed from C++ rand()?

前端 未结 8 675
名媛妹妹
名媛妹妹 2020-12-31 01:49

I generate a few thousand object in my program based on the C++ rand() function. Keeping them in the memory would be exhaustive. Is there a way to copy the CURRENT

相关标签:
8条回答
  • 2020-12-31 02:09

    Use srand() to set the seed. save the value you used as the seed.

    http://cplusplus.com/reference/clibrary/cstdlib/srand/

    0 讨论(0)
  • 2020-12-31 02:12

    Does anyone know other random number generators with implemented seed-stealer

    All standard C++11 random number generators (also available in TR1 and in Boost) offer this functionality. You can simply copy the generator objects or serialize/deserialize them.

    0 讨论(0)
  • 2020-12-31 02:15

    Is there a way to copy the CURRENT seed of rand() at any given time?

    What follows is an implementation-specific way to save and restore the pseudo-random number generator (PRNG) state that works with the C library on Ubuntu Linux (tested on 14.04 and 16.04).

    #include <array>
    #include <cstdlib>
    #include <iostream>
    
    using namespace std;
    
    constexpr size_t StateSize = 128;
    using RandState = array<char, StateSize>;
    
    void save(RandState& state) {
        RandState tmpState;
        char* oldState = initstate(1, tmpState.data(), StateSize);
        copy(oldState, oldState + StateSize, state.data());
        setstate(oldState);
    }
    
    void restore(RandState& state) {
        setstate(state.data());
    }
    
    int main() {
        cout << "srand(1)\n";
    
        srand(1);
    
        cout << "  rand(): " << rand() << '\n';
        cout << "  rand(): " << rand() << '\n';
        cout << "  rand(): " << rand() << '\n';
        cout << "  rand(): " << rand() << '\n';
        cout << "  rand(): " << rand() << '\n';
        cout << "  rand(): " << rand() << '\n';
        cout << "  rand(): " << rand() << '\n';
        cout << "  rand(): " << rand() << '\n';
    
        cout << "srand(1)\n";
    
        srand(1);
    
        cout << "  rand(): " << rand() << '\n';
        cout << "  rand(): " << rand() << '\n';
        cout << "  rand(): " << rand() << '\n';
        cout << "  rand(): " << rand() << '\n';
    
        cout << "save()\n";
    
        RandState state;
        save(state);
    
        cout << "  rand(): " << rand() << '\n';
        cout << "  rand(): " << rand() << '\n';
        cout << "  rand(): " << rand() << '\n';
        cout << "  rand(): " << rand() << '\n';
    
        cout << "restore()\n";
    
        restore(state);
    
        cout << "  rand(): " << rand() << '\n';
        cout << "  rand(): " << rand() << '\n';
        cout << "  rand(): " << rand() << '\n';
        cout << "  rand(): " << rand() << '\n';
    }
    

    This relies on:

    1. the same PRNG being used by the C library to expose both rand() and random() interfaces, and
    2. some knowledge about the default initialization of this PRNG in the C library (128 bytes state).

    If run, this should output:

    srand(1)
      rand(): 1804289383
      rand(): 846930886
      rand(): 1681692777
      rand(): 1714636915
      rand(): 1957747793
      rand(): 424238335
      rand(): 719885386
      rand(): 1649760492
    srand(1)
      rand(): 1804289383
      rand(): 846930886
      rand(): 1681692777
      rand(): 1714636915
    save()
      rand(): 1957747793
      rand(): 424238335
      rand(): 719885386
      rand(): 1649760492
    restore()
      rand(): 1957747793
      rand(): 424238335
      rand(): 719885386
      rand(): 1649760492
    

    This solution can help in some cases (code that can't be changed, reproducing execution for debugging purpose, etc...), but it is obviously not recommended as a general one (e.g. use C++11 PRNG which properly support this).

    0 讨论(0)
  • 2020-12-31 02:18

    There's no standard way to obtain the current seed (you can only set it via srand), but you can reimplement rand() (which is usually a linear congruential generator) by yourself in a few lines of code:

    class LCG
    {
    private:
        unsigned long next = 1;
    public:
    
        LCG(unsigned long seed) : next(seed) {}
    
        const unsigned long rand_max = 32767
    
        int rand()
        {
            next = next * 1103515245 + 12345;
            return (unsigned int)(next/65536) % 32768;
        }
    
        void reseed(unsigned long seed)
        {
            next = seed;
        }
    
        unsigned long getseed()
        {
            return next;
        }
    };
    
    0 讨论(0)
  • 2020-12-31 02:19

    You could try saving the value that you used to seed right before (or after) the srand.

    So, for example:

    int seed = time(NULL);
    srand(time(NULL));
    
    cout << seed << endl;
    cout << time(NULL);
    

    The two values should be the same.

    0 讨论(0)
  • 2020-12-31 02:21

    The random number generation classes in C++11 support operator<< to store their state (mostly the seed) and operator>> to read it back in. So, basically, before you create your objects, save the state, then when you need to re-generate same sequence, read the state back in, and off you go.

    0 讨论(0)
提交回复
热议问题