QT6 源(34):随机数生成器类 QRandomGenerator 的源码阅读

(1)代码来自 qrandom.h ,结合官方的注释

#ifndef QRANDOM_H
#define QRANDOM_H

#include <QtCore/qalgorithms.h>
#include <algorithm>    // for std::generate
#include <random>       // for std::mt19937

#ifdef min
#  undef min
#endif
#ifdef max
#  undef max
#endif

QT_BEGIN_NAMESPACE  //说明本类直接定义在 QT 的命名空间

class QRandomGenerator //Note: All functions in this class are reentrant.
{
    // restrict the template parameters to
    // unsigned integers 32 bits wide or larger
    // 为 true 时要求模板参数 UINT 在 32bit 以上
    template <typename UInt> //定义模板变量,本值是布尔量
    using IfValidUInt = typename std::enable_if<
        std::is_unsigned<UInt>::value &&
            sizeof(UInt) >= sizeof(uint), bool>::type;

private: //私有部分会包含重要的数据成员的定义
    //typedef  QIntegerForSizeof<void *>::Signed  qptrdiff;
    Q_CORE_EXPORT quint64 _fillRange(void *buffer, qptrdiff count);
    //应该是从 buffer 地址开始填充 count 个随机数

    struct InitialRandomData { //本类用作下面的友元函数的返回值类型
        //typedef QIntegerForSizeof<void *>::Unsigned quintptr;
        quintptr data[16 / sizeof(quintptr)]; //sizeof(quintptr) = 8
    };

    friend InitialRandomData qt_initial_random_value() noexcept; //友元函数

    friend class QRandomGenerator64 ; //友元类

    struct SystemGenerator          ; //类声明
    struct SystemAndGlobalGenerators;

    using RandomEngine = std::mersenne_twister_engine< //模板别名
        quint32, 32,624,397,31,0x9908b0df,11,0xffffffff,7,
        0x9d2c5680,15,0xefc60000,18,1812433253>;

    union Storage //定义了类中类
    {
        uint dummy ;           //本类的数据成员
#ifdef Q_COMPILER_UNRESTRICTED_UNIONS //if分支有效
        RandomEngine twister;  //本类的成员变量
              RandomEngine & engine()       { return twister; }
        const RandomEngine & engine() const { return twister; }
#else                                 //else分支作废
        std::aligned_storage<sizeof(RandomEngine), alignof(RandomEngine)>::type buffer;
        RandomEngine &engine() { return reinterpret_cast<RandomEngine &>(buffer); }
        const RandomEngine &engine() const { return reinterpret_cast<const RandomEngine &>(buffer); }
#endif

        static_assert(std::is_trivially_destructible<RandomEngine>::value,
    "std::mersenne_twister not trivially平凡地 destructible as expected");

        constexpr Storage(); //本类的默认构造函数
    };
    Storage storage; //本随机类的数据成员
    uint    type   ; //又一个数据成员

public:
    //Initializes this QRandomGenerator object with the value seedValue
    //as the seed. Two objects constructed or reseeded with the same seed value
    //will produce the same number sequence.
    QRandomGenerator(quint32 seedValue = 1)  //本类的有参构造函数
        : QRandomGenerator(&seedValue, 1) {} //带默认参数,也可以作为无参构造函数

    //Initializes this QRandomGenerator object
    //with the values found in the array seedBuffer as the seed.
    //Two objects constructed or reseeded with the same seed value
    //will produce the same number sequence.
    //可以这么用: uint t[3]={1,2,3};  //此处必须是无符号数组, int 数组会报错
    //      QRandomGenerator ma(t);
    template <qsizetype N> //普通类型的模板参数,必须给值的
    QRandomGenerator(const quint32 (&seedBuffer)[N]) //形参是整型数组
        : QRandomGenerator(seedBuffer, seedBuffer + N) {}

    //Initializes this QRandomGenerator object
    //with len values found in the array seedBuffer as the seed.
    QRandomGenerator(const quint32 * seedBuffer, qsizetype len)
        : QRandomGenerator(seedBuffer, seedBuffer + len) {}

    Q_CORE_EXPORT QRandomGenerator(std::seed_seq & sseq) noexcept;//构造函数

    //Initializes this QRandomGenerator object
    //with the values found in the range from begin to end as the seed.
    Q_CORE_EXPORT QRandomGenerator(const quint32 *begin, const quint32 *end);


    //本类的静态成员函数,返回一个指针,指向随机数生成器对象。英文注释讲解略
    //返回一个指向共享ORandomGenerator的指针,
    //该共享ORandomGenerator总是使用操作系统提供的工具来生成随机数。
    //系统设施在至少以下操作系统上被认为是加密安全的:苹果操作系统(Darwin)、BSD、
    //Linux、Windows。在其他操作系统上也可能出现这种情况。
    //他们也可能支持一个真正的硬件随机数发生器。
    //因此,此函数返回的ORandomGenerator不应用于批量数据生成。
    //相反,可以用它从<random>头部种子化ORandomGenerator或一个随机引擎。
    //此函数返回的对象是线程安全的,可以在任何线程中使用,无需锁定。
    //它也可以被复制,生成的 ORandomGenerator也会访问操作系统设施,但它们不会生成相同的序列。
    static inline Q_DECL_CONST_FUNCTION QRandomGenerator * system();
    //老师说不要用这个函数大量生成随机数据,只用来生成种子即可。!!!!++++

    //返回一个共享的QRandomGenerator的指针,该指针使用securelySeeded()进行初始化。
    //此函数应用于创建随机数据,
    //而无需为特定用途创建昂贵的securely-seeded ORandomGenerator
    //或存储较大的 QRandomGenerator对象。
    //对这个对象的访问是线程安全的,因此可以在任何线程中使用,无需锁定。
    //该对象也可以被复制,而复制产生的序列将与共享对象产生的序列相同。
    //但是,请注意,如果有其他线程访问全局对象,这些线程可能会在不可预测的间隔内获取样本。
    static inline Q_DECL_CONST_FUNCTION QRandomGenerator * global();//返回指针
    //老师说,一般情况用这个静态函数就足够了。!!!!!++++++


    //返回一个新的 QRandomGenerator 对象,该对象通过 QRandomGenerator:system()
    //安全地进行了初始化。此函数将为 ORandomGenerator 使用的算法获取理想的种子大小,
    //因此是创建将保留-段时间的新 ORandomGenerator 对象的推荐方法。
    //考虑到安全启动确定性引擎所需的数据量,这个函数有些昂贵,
    //不应用于QRandomGenerator 的短期使用
    //(使用它生成少于 2600 字节的随机数据实际上是一种资源浪费)。
    //如果使用不需要那么多数据,可以考虑使用 ORandomGenerator::global()
    //而不是存储一个 ORandomGenerator 对象。
    static inline QRandomGenerator securelySeeded();  //返回生成器对象

    // copy constructor & assignment operator (move unnecessary)
    Q_CORE_EXPORT QRandomGenerator(const QRandomGenerator &other);
    //copy 构造函数与 copy 赋值运算符函数
    Q_CORE_EXPORT QRandomGenerator & operator=(const QRandomGenerator & other);

    friend Q_CORE_EXPORT bool //声明了全局友元函数
    operator==(const QRandomGenerator &rng1, const QRandomGenerator &rng2);

    friend bool operator!=(const QRandomGenerator &rng1,
                           const QRandomGenerator &rng2  )
    {
        return !(rng1 == rng2);
    }

    //Generates a 32-bit random quantity数量 and returns it.
    //调用了本类的私有成员函数 _fillRange()以实现本函的功能
    quint32 generate() { return quint32(_fillRange(nullptr, 1));  }

    //Generates a 64-bit random quantity and returns it.
    quint64 generate64()
    {
        return _fillRange(nullptr, sizeof(quint64) / sizeof(quint32));
    }

    //Generates one random qreal in the canonical range [0, 1)
    //(that is, inclusive of zero and exclusive of 1).
    double generateDouble()
    {
        // IEEE 754 double precision has: 双精度数值,共 64 bit 8字节
        //   1 bit      sign
        //  10 bits     exponent  指数部分
        //  53 bits     mantissa  有效数字
        // In order for our result to be normalized in the range [0, 1), we
        // need exactly 53 bits of random data. Use generate64() to get enough.
        quint64     x = generate64();
        quint64 limit = Q_UINT64_C(1) << std::numeric_limits<double>::digits;

        x >>= std::numeric_limits<quint64>::digits - //这是个减法运算
              std::numeric_limits<double> ::digits ;

        return double(x) / double(limit);
    }

    //Generates 32-bit quantities and stores them
    //in the range between begin and end.
    // API like std::seed_seq
    template <typename ForwardIterator>
    void generate(ForwardIterator begin, ForwardIterator end)
    {
        std::generate(begin, end, [this]() { return generate(); });
    }

    void generate(quint32 *begin, quint32 *end)
    {
        _fillRange(begin, end - begin);
    }

    //generate 与 bound 差不多,前者的取值不受限制,后者有突出边界上限的意思。

    //Generates one random double in the range between 0 (inclusive) and
    //highest (exclusive).
    //This function is equivalent to and is implemented as:
    //     return generateDouble() * highest; 此行是本函数的实现原理
    //If the highest parameter is negative,
    //the result will be negative too;
    //if it is infinite or NaN,
    //the result will be infinite or NaN too (that is, not random).
    double bounded(double highest) //形参是 double 类型
    {
        return generateDouble() * highest;
    }

    //typedef unsigned int quint32;
    quint32 bounded(quint32 highest) //形参是 32 位无符号整数
    {
        quint64 value = generate();
        value *= highest;            //先乘法后除法才不会损失精度
        value /= (max)() + quint64(1);
        return quint32(value);
    }

    //Generates one random 32-bit quantity in the range between 0 (inclusive)
    //and highest (exclusive). highest must be positive.
    int bounded(int highest)    //函数重载
    {
        Q_ASSERT(highest > 0);
        return int(bounded(0U, quint32(highest)));
    }

    qint64 bounded(qint64  highest) //形参的无符号与有符号版本
    {
        Q_ASSERT(highest > 0);
        return qint64(bounded(quint64(0), quint64(highest)));
    }

    quint64 bounded(quint64 highest);

    //Generates one random 32-bit quantity in the range between
    //lowest (inclusive) and highest (exclusive).
    //The highest parameter must be greater than lowest.
    quint32 bounded(quint32 lowest, quint32 highest)
    {
        Q_ASSERT(highest > lowest);
        return bounded(highest - lowest) + lowest;
    }

    int bounded(int lowest, int highest)
    {
        return bounded(highest - lowest) + lowest;
    }

    quint64 bounded(quint64 lowest, quint64 highest)
    {
        Q_ASSERT(highest > lowest);
        return bounded(highest - lowest) + lowest;
    }

    qint64 bounded(qint64 lowest, qint64 highest)
    {
        return bounded(highest - lowest) + lowest;
    }

    // these functions here only to help with ambiguous overloads
    qint64 bounded(int lowest, qint64 highest)
    {
        return bounded(qint64(lowest), qint64(highest));
    }

    qint64 bounded(qint64 lowest, int highest)
    {
        return bounded(qint64(lowest), qint64(highest));
    }

    quint64 bounded(unsigned lowest, quint64 highest)
    {
        return bounded(quint64(lowest), quint64(highest));
    }
    quint64 bounded(quint64 lowest, unsigned highest)
    {
        return bounded(quint64(lowest), quint64(highest));
    }


    //Generates count 32- or 64-bit quantities (depending on the type UInt)
    //and stores them in the buffer pointed by buffer.
    //This is the most efficient way to obtain more than one quantity at a time,
    //as it reduces the number of calls into the Random Number Generator source.
    template <typename UInt, IfValidUInt<UInt> = true>
    void fillRange(UInt * buffer, qsizetype count)
    {
        _fillRange(buffer, count * sizeof(UInt) / sizeof(quint32));
    }

    //Generates N 32- or 64-bit quantities (depending on the type UInt)
    //and stores them in the buffer array.
    template <typename UInt, size_t N, IfValidUInt<UInt> = true>
    void fillRange(UInt (&buffer)[N]) //形参是数组名的类型,N由模板参数确定了
    {
        _fillRange(buffer, N * sizeof(UInt) / sizeof(quint32));
    }

    // API like std:: random engines
    typedef quint32 result_type; //重载了括号 () 运算符,使本类成为了可调用对象
    result_type operator()() { return generate(); }

    //Reseeds this object using the value seed as the seed.
    void seed(quint32 s = 1) { *this = { s }; }

    void seed(std::seed_seq & sseq) noexcept { *this = { sseq }; }

    //Discards the next z entries from the sequence.
    //This method is equivalent to calling generate() z times
    //and discarding the result, 形参是丢掉 z 个随机数
    Q_CORE_EXPORT void discard(unsigned long long z);

    //Returns the minimum value that QRandomGenerator may ever generate.
    //That is, 0.
    static constexpr result_type min()
    { return std::numeric_limits<result_type>::min(); }

    //Returns the maximum value that QRandomGenerator may ever generate.
    //That is, std::numeric_limits<result_type>::max().
    static constexpr result_type max()
    { return std::numeric_limits<result_type>::max(); }

protected:
    enum System {}; //本类的 protected 属性的成员函数
    QRandomGenerator(System); //这是一个构造函数

};

class QRandomGenerator64 : public QRandomGenerator //子类的 64 bit 生成器
{
    QRandomGenerator64(System);
public:
    // unshadow generate() overloads, since we'll override.
    using QRandomGenerator::generate;
    quint64 generate() { return generate64(); }

    typedef quint64 result_type;
    result_type operator()() { return generate64(); }

#ifndef Q_QDOC
    QRandomGenerator64(quint32 seedValue = 1)
        : QRandomGenerator(seedValue) {}

    template <qsizetype N>
    QRandomGenerator64(const quint32 (&seedBuffer)[N])
        : QRandomGenerator(seedBuffer) {}

    QRandomGenerator64(const quint32 *seedBuffer, qsizetype len)
        : QRandomGenerator(seedBuffer, len) {}

    QRandomGenerator64(std::seed_seq &sseq) noexcept
        : QRandomGenerator(sseq) {}

    QRandomGenerator64(const quint32 *begin, const quint32 *end)
        : QRandomGenerator(begin, end) {}

    QRandomGenerator64(const QRandomGenerator &other)
        : QRandomGenerator(other) {}

    void discard(unsigned long long z)
    {
        Q_ASSERT_X(z * 2 > z, "QRandomGenerator64::discard",
                   "Overflow. Are you sure you want to skip over 9 quintillion samples?");
        QRandomGenerator::discard(z * 2);
    }

    static constexpr result_type min()
    { return std::numeric_limits<result_type>::min(); }

    static constexpr result_type max()
    { return std::numeric_limits<result_type>::max(); }

    static Q_DECL_CONST_FUNCTION Q_CORE_EXPORT QRandomGenerator64 *system();
    static Q_DECL_CONST_FUNCTION Q_CORE_EXPORT QRandomGenerator64 *global();
    static Q_CORE_EXPORT QRandomGenerator64 securelySeeded();
#endif // Q_QDOC
};

inline quint64 QRandomGenerator::bounded(quint64 highest)
{
    // Implement an algorithm similar to libc++'s uniform_int_distribution:
    // loop around getting a random number, mask off any bits that "highest"
    // will never need, then check if it's higher than "highest". The number of
    // times the loop will run is unbounded but the probability of terminating
    // is better than 1/2 on each iteration. Therefore, the average loop count
    // should be less than 2.

    const int width = qCountLeadingZeroBits(highest - 1);
    const quint64 mask = (quint64(1) << (std::numeric_limits<quint64>::digits - width)) - 1;
    quint64 v;
    do {
        v = generate64() & mask;
    } while (v >= highest);
    return v;
}

inline QRandomGenerator * QRandomGenerator::system()
{   //本函利用系统资源生成随机数生成器
    return QRandomGenerator64::system();
}

inline QRandomGenerator * QRandomGenerator::global()
{
    return QRandomGenerator64::global();
}

//由这里可见,子类的 64 bit的随机数生成器更重要,更基础。

QRandomGenerator QRandomGenerator::securelySeeded()
{
    return QRandomGenerator64::securelySeeded();
}

QT_END_NAMESPACE

#endif // QRANDOM_H

(2)

谢谢

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值