Jeroen
Jeroen

Reputation: 16815

Get random number in sequence C++

Is there a way using the C++ standard library built in random generator to get a specific random number in a sequence, without saving them all?

Like

srand(cTime);
getRand(1); // 10
getRand(2); // 8995
getRand(3); // 65464456
getRand(1); // 10
getRand(2); // 8995
getRand(1); // 10
getRand(3); // 65464456

Upvotes: 1

Views: 2138

Answers (5)

Casey
Casey

Reputation: 42554

C++11 random number engines are required to implement a member function discard(unsigned long long z) (§26.5.1.4) that advances the random number sequence by z steps. The complexity guarantee is quite weak: "no worse than the complexity of z consecutive calls e()". This member obviously exists solely to make it possible to expose more performant implementations when possible as note 274 states:

This operation is common in user code, and can often be implemented in an engine-specific manner so as to provide significant performance improvements over an equivalent naive loop that makes z consecutive calls e().

Given discard you can easily implement your requirement to retrieve the nth number in sequence by reseeding a generator, discarding n-1 values and using the next generated value.

I'm unaware of which - if any - of the standard RNG engines are amenable to efficient implementations of discard. It may be worth your time to do a bit of investigation and profiling.

Upvotes: 1

c-urchin
c-urchin

Reputation: 4504

Check out: Random123

From the documentation:

Random123 is a library of "counter-based" random number generators (CBRNGs), in which the Nth random number can be obtained by applying a stateless mixing function to N..

Upvotes: 0

P0W
P0W

Reputation: 47794

Similar to cdmh's post,

Following from C++11 could also be used :

#include<random>

long getrand(int index)
{
 std::default_random_engine e;
 for(auto i=1;i<index;i++)
     e();
  return e();
}

Upvotes: 0

cdmh
cdmh

Reputation: 3344

Implement getRand() to always seed and then return the given number. This will interfere with all other random numbers in a system, though, and will be slow, especially for large indexes. Assuming a 1-based index:

int getRand(int index)
{
    srand(999);  // fix the seed
    for (int loop=1; loop<index; ++loop)
        rand();
    return rand();
}

Upvotes: 0

Mats Petersson
Mats Petersson

Reputation: 129374

You have to save the numbers. There may be other variants, but it still requires saving a list of numbers (e.g. using different seeds based on the argument to getRand() - but that wouldn't really be beneficial over saving them).

Something like this would work reasonably well, I'd say:

int getRand(int n)
{
    static std::map<int, int> mrand;
    // Check if it's there. 
    if ((std::map::iterator it = mrand.find(n)) != mrand.end())
    {
        return it->second;
    }

    int r = rand();
    mrand[n] = r;
    return r;
}

(I haven't compiled this code, just written it up as a "this sort of thing might work")

Upvotes: 1

Related Questions