Вопрос

So I've got a custom randomizer class that uses a Mersenne Twister (the code I use is adapted from this site). All seemed to be working well, until I started testing different seeds (I normally use 42 as a seed, to ensure that each time I run my program, the results are the same, so I can see how code changes influence things).

It turns out that, no matter what seed I choose, the code produces the exact same series of numbers each time. Clearly I'm doing something wrong, but I don't know what. Here is my seed function:

void Randomizer::Seed(unsigned long int Seed)
{
    int ii;
    x[0] = Seed & 0xffffffffUL;
    for (ii = 0; ii < N; ii++)
    {
        x[ii] = (1812433253UL * (x[ii - 1] ^ (x[ii - 1] >> 30)) + ii);
        x[ii] &= 0xffffffffUL;
    }
}

And this is my Rand() function

unsigned long int Randomizer::Rand()
{
    unsigned long int Result;
    unsigned long int a;
    int ii;

    // Refill x if exhausted
    if (Next == N)
    {
        Next = 0;

        for (ii = 0; ii < N - 1; ii++)
        {
            Result = (x[ii] & U) | x[ii + 1] & L;
            a = (Result & 0x1UL) ? A : 0x0UL;
            x[ii] = x[( ii + M) % N] ^ (Result >> 1) ^ a;
        }

        Result = (x[N - 1] & U) | x[0] & L;
        a = (Result & 0x1UL) ? A : 0x0UL;
        x[N - 1] = x[M - 1] ^ (Result >> 1) ^ a;
    }
    Result = x[Next++];

    //Improves distribution
    Result ^= (Result >> 11);
    Result ^= (Result << 7) & 0x9d2c5680UL;
    Result ^= (Result << 15) & 0xefc60000UL;
    Result ^= (Result >> 18);

    return Result;
}

The various values are:

#define A 0x9908b0dfUL
#define U 0x80000000UL
#define L 0x7fffffffUL

int Randomizer::N = 624;
int Randomizer::M = 397;
int Randomizer::Next = 0;
unsigned long Randomizer::x[624];

Can anyone help me figure out why different seeds don't result in different sequences of numbers?

Это было полезно?

Решение

Your Seed() function assigns to x[0], then starts looping at ii=0, which overwrites x[0] with an undefined value (it references x[-1]). Start your loop at 1, and you'll probably be all set.

Writing your own randomizer is dangerous. Why? It's hard to get right (see above), it's hard to know if you've done it right, and if it's wrong, things that rely on correctly distributed random numbers will not work quite right. Hopefully that thing is not cryptography or statistical modeling where the tails matter.... Think about using std::random, or if you're not on C++11 yet, boost::random.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top