如何将 GCCRandomTakuji Nishimura 和 Makoto Matsumoto 的 Mersenne Twister从 Mike McShaffry 4E 的 Game Coding Complete 转换为 stl random

问题描述

我正在尝试将 Mike McShaffry 4E 的 Game Coding Complete 一书翻译成现代 C++17 标准,并面对 Takuji Nishimura 和 Makoto Matsumoto 的 Mersenne Twister 代码。 像这样从书中转换随机生成代码是否正确: 来自:

#include <ctime>
#define CMATH_N 624
#define CMATH_M 397
#define CMATH_MATRIX_A 0x9908b0df   /* constant vector a */
#define CMATH_UPPER_MASK 0x80000000 /* most significant w-r bits */
#define CMATH_LOWER_MASK 0x7fffffff /* least significant r bits */
#define CMATH_TEMPERING_MASK_B 0x9d2c5680
#define CMATH_TEMPERING_MASK_C 0xefc60000
#define CMATH_TEMPERING_SHIFT_U(y)  (y >> 11)
#define CMATH_TEMPERING_SHIFT_S(y)  (y << 7)
#define CMATH_TEMPERING_SHIFT_T(y)  (y << 15)
#define CMATH_TEMPERING_SHIFT_L(y)  (y >> 18)
typedef int INT;
typedef unsigned int UINT;
#define MAXUINT ((UINT)~((UINT)0))
#define MAXINT ((INT)(MAXUINT >> 1))
class GCCRandom {
private:
    unsigned int rseed;
    unsigned int rseed_sp;
    unsigned long mt[CMATH_N]; /* the array for the state vector  */
    int mti; /* mti==N+1 means mt[N] is not initialized */
public:
    GCCRandom() {
        rseed = 1;
        rseed_sp = 0;
        mti = CMATH_N + 1;
    }
    unsigned int Random(unsigned int n) {
        unsigned long y;
        static unsigned long mag01[2] = { 0x0,CMATH_MATRIX_A };
        if (n == 0)
            return(0);
        if (mti >= CMATH_N) { /* generate N words at one time */
            int kk;
            if (mti == CMATH_N + 1)   /* if sgenrand() has not been called,*/
                SetRandomSeed(4357); /* a default initial seed is used   */
            for (kk = 0; kk < CMATH_N - CMATH_M; kk++) {
                y = (mt[kk] & CMATH_UPPER_MASK) | (mt[kk + 1] & CMATH_LOWER_MASK);
                mt[kk] = mt[kk + CMATH_M] ^ (y >> 1) ^ mag01[y & 0x1];
            }
            for (; kk < CMATH_N - 1; kk++) {
                y = (mt[kk] & CMATH_UPPER_MASK) | (mt[kk + 1] & CMATH_LOWER_MASK);
                mt[kk] = mt[kk + (CMATH_M - CMATH_N)] ^ (y >> 1) ^ mag01[y & 0x1];
            }
            y = (mt[CMATH_N - 1] & CMATH_UPPER_MASK) | (mt[0] & CMATH_LOWER_MASK);
            mt[CMATH_N - 1] = mt[CMATH_M - 1] ^ (y >> 1) ^ mag01[y & 0x1];
            mti = 0;
        }
        y = mt[mti++];
        y ^= CMATH_TEMPERING_SHIFT_U(y);
        y ^= CMATH_TEMPERING_SHIFT_S(y) & CMATH_TEMPERING_MASK_B;
        y ^= CMATH_TEMPERING_SHIFT_T(y) & CMATH_TEMPERING_MASK_C;
        y ^= CMATH_TEMPERING_SHIFT_L(y);
        return (y % n);
    }
    float Random() {
        float r = (float)Random(MAXINT);
        float divisor = (float)MAXINT;
        return (r / divisor);
    }
    void SetRandomSeed(unsigned int n) {
        /* setting initial seeds to mt[N] using         */
        /* the generator Line 25 of Table 1 in          */
        /* [knuth 1981,The Art of Computer Programming */
        /*    Vol. 2 (2nd Ed.),pp102]                  */
        mt[0] = n & 0xffffffff;
        for (mti = 1; mti < CMATH_N; mti++)
            mt[mti] = (69069 * mt[mti - 1]) & 0xffffffff;
        rseed = n;
    }
    unsigned int GetRandomSeed() {
        return rseed;
    }
    void Randomize() {
        SetRandomSeed((unsigned int)time(NULL));
    }
};

使用 std::mt19937 引擎和 std::uniform_int_distribution 进行编码:

#include <random>
#include <limits>
#include <chrono>
class MTRandom {
private:
    unsigned int m_rseed = 1;
    unsigned int m_rseed_sp = 0;
    static const unsigned int MAXINT = std::numeric_limits<int>::max();
    std::mt19937 m_engine;
public:
    MTRandom() { m_engine.seed(m_rseed); }
    unsigned int Random(unsigned int n) {
        std::uniform_int_distribution<unsigned int> distr(0,n);
        return distr(m_engine);
    };
    float Random() {
        std::uniform_real_distribution<float> distr(0.0f,1.0f);
        return distr(m_engine);        
    }
    void SetRandomSeed(unsigned int n) {
        m_engine.seed(n);
        m_rseed = n;
    }
    unsigned int GetRandomSeed() {
        return m_rseed;
    }
    void Randomize() {
        SetRandomSeed((unsigned int)std::chrono::system_clock::to_time_t(std::chrono::system_clock::Now()));
    }
};

解决方法

暂无找到可以解决该程序问题的有效方法,小编努力寻找整理中!

如果你已经找到好的解决方法,欢迎将解决方案带上本链接一起发送给小编。

小编邮箱:dio#foxmail.com (将#修改为@)