简体   繁体   English

生成伪随机16位整数

[英]Generating pseudo-random 16-bit integers

I need to generate 16-bit pseudo-random integers and I am wondering what the best choice is. 我需要生成16位伪随机整数,我想知道最好的选择是什么。

The obvious way that comes in my mind is something as follows: 我想到的显而易见的方法如下:

std::random_device rd;
auto seed_data = std::array<int, std::mt19937::state_size> {};
std::generate(std::begin(seed_data), std::end(seed_data), std::ref(rd));
std::seed_seq seq(std::begin(seed_data), std::end(seed_data));
std::mt19937 generator(seq);
std::uniform_int_distribution<short> dis(std::numeric_limits<short>::min(), 
                                         std::numeric_limits<short>::max());

short n = dis(generator);

The problem I see here is that std::mt19937 produces 32-bit unsigned integers since it's defined as this: 我在这里看到的问题是std::mt19937产生32位无符号整数,因为它被定义为:

using mt19937 = mersenne_twister_engine<unsigned int, 
                                        32, 624, 397, 
                                        31, 0x9908b0df,
                                        11, 0xffffffff, 
                                        7, 0x9d2c5680, 
                                        15, 0xefc60000, 
                                        18, 1812433253>;

That means static casting is done and only the least significant part of these 32-bit integers is used by the distribution. 这意味着静态转换已完成,并且分布仅使用这些32位整数的最不重要部分。 So I am wondering how good are these series of pseudo-random shorts and I don't have the mathematical expertise to answer that. 所以我想知道这些伪随机短裤系列有多好,我没有数学专业知识来回答这个问题。

I expect that a better solution would be to use your own defined mersenne_twister_engine engine for 16-bit integers. 我希望更好的解决方案是使用您自己定义的mersenne_twister_engine引擎来获得16位整数。 However, I haven't found any mentioned set for the template arguments (requirements can be found here for instance). 但是,我没有找到任何提到的模板参数集(例如,可以在这里找到需求)。 Are there any? 有吗?

UPDATE : I updated the code sample with proper initialization for the distribution. 更新 :我通过正确的分发初始化更新了代码示例。

Your way is indeed the correct way. 你的方式确实是正确的方法。

The mathematical arguments are complex (I'll try to dig out a paper), but taking the least significant bits of the Mersenne Twister, as implemented by the C++ standard library, is the correct thing to do. 数学论证是复杂的(我将尝试挖掘一篇论文),但是采用由C ++标准库实现的Mersenne Twister中最不重要的部分是正确的做法。

If you're in any doubt as to the quality of the sequence, then run it through the diehard tests. 如果您对序列的质量有任何疑问,请通过死硬测试。

There may be a misconception, considering this quote from OP's question (emphasis mine): 考虑到OP的问题(强调我的),这可能存在一种误解:

The problem I see here is that std::mt19937 produces 32-bit unsigned integers […]. 我在这里看到的问题是std :: mt19937产生32位无符号整数[...]。 That means static casting is done and only the least significant part of these 32-bit integers is used by the distribution . 这意味着静态转换已完成,并且分布仅使用这些32位整数的最不重要部分

That's not how it works. 这不是它的工作原理。

The following are quotes from https://en.cppreference.com/w/cpp/numeric/random 以下是https://en.cppreference.com/w/cpp/numeric/random的引用

The random number library provides classes that generate random and pseudo-random numbers. 随机数库提供生成随机和伪随机数的类。 These classes include: 这些课程包括:

  • Uniform random bit generators (URBGs), […]; 均匀随机比特生成器(URBG),[...];
  • Random number distributions (eg uniform, normal, or poisson distributions) which convert the output of URBGs into various statistical distributions 随机数分布(例如均匀分布,正态分布或泊松分布)将URBG的输出转换为各种统计分布

URBGs and distributions are designed to be used together to produce random values. URBG和分布旨在一起使用以产生随机值。

So a uniform random bit generator, like mt19937 or random_device 所以一个统一的随机比特生成器,如mt19937random_device

is a function object returning unsigned integer values such that each value in the range of possible results has (ideally) equal probability of being returned. 是一个函数对象,返回无符号整数值,使得可能结果范围内的每个值(理想情况下)返回的概率相等。

While a random number distribution, like uniform_int_distribution 而随机数分布,如uniform_int_distribution

post-processes the output of a URBG in such a way that resulting output is distributed according to a defined statistical probability density function. 以这样的方式URBG的输出进行后处理 ,使得根据定义的统计概率密度函数分配所得到的输出。

The way it's done uses all the bits from the source to produce an output. 它的完成方式使用源中的所有位来产生输出。 As an example, we can look at the implementation of std::uniform_distribution in libstdc++ (starting at line 824), which can be roughly simplified as 作为一个例子,我们可以看一下libstdc++std::uniform_distribution的实现(从第824行开始),它大致可以简化为

template <typename Type>
class uniform_distribution
{
    Type a_ = 0, b_ = std::numeric_limits<Type>::max();
public:
    uniform_distribution(Type a, Type b) : a_{a}, b_{b} {}
    template<typename URBG>
    Type operator() (URBG &gen)
    {
        using urbg_type = std::make_unsigned_t<typename URBG::result_type>;
        using u_type    = std::make_unsigned_t<Type>;
        using max_type  = std::conditional_t<(sizeof(urbg_type) > sizeof(u_type))
                                            , urbg_type, u_type>;

        urbg_type urbg_min = gen.min();
        urbg_type urbg_max = gen.max();
        urbg_type urbg_range = urbg_max - urbg_min;

        max_type urange = b_ - a_;
        max_type udenom = urbg_range <= urange ? 1 : urbg_range / (urange + 1);

        Type ret;
        // Note that the calculation may require more than one call to the generator
        do
            ret = (urbg_type(gen()) - urbg_min ) / udenom;
            // which is 'ret = gen / 65535' with OP's parameters
            // not a simple cast or bit shift
        while (ret > b_ - a_);
        return ret + a_;
    }
};

This could be tested HERE . 这可以在这里测试。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM