(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
#endifQT_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); }
#endifstatic_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_seqtemplate <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 overloadsqint64 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 enginestypedef 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_QDOCQRandomGenerator64(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)
謝謝