c++ 11中的随机数生成:如何生成,如何工作
Random number generation in C++11: how to generate, how does it work?
我最近遇到了在c++ 11中生成随机数的新方法,但无法消化我读过的关于它的论文(引擎是什么,数学术语,如分布,"所有生成的整数等可能")。
谁能解释一下
- 它们是什么?
- 它们是什么意思?
- 如何生成?
- 它们是如何工作的? 等
关于随机数生成的常见问题解答
这个问题太宽泛了,不可能给出一个完整的答案,但让我挑选几个有趣的点:
为什么"等可能"
假设你有一个简单的随机数生成器,它生成数字0,1,…,每10个都有相同的概率(把它想象成经典的rand()
)。现在你想要一个在0,1,2范围内的随机数,每个随机数的概率是相等的。你的本能反应是选择rand() % 3
。但是等等,余数0和1比余数2出现的次数更多,所以这是不正确的!
这就是为什么我们需要合适的分布,它采用一致随机整数的源并将它们转换为我们想要的分布,如示例中的Uniform[0,2]
。最好把这个问题留给一个好的图书馆!
引擎/h3>
因此,在所有随机性的核心是一个好的伪随机数生成器,它生成在一定间隔内均匀分布的数字序列,并且理想情况下具有很长的周期。rand()
的标准实现通常不是最好的,因此最好有一个选择。线性同余和Mersenne twister是两个不错的选择(实际上rand()
也经常使用LG);还是那句话,最好让库来处理。
工作原理
简单:首先,设置一个引擎并播种它。种子完全决定了"随机"数字的整个序列,所以a)每次使用不同的一个(例如从/dev/urandom
中取出),b)如果您希望重新创建随机选择序列,则存储种子。
#include <random>
typedef std::mt19937 MyRNG; // the Mersenne Twister with a popular choice of parameters
uint32_t seed_val; // populate somehow
MyRNG rng; // e.g. keep one global instance (per thread)
void initialize()
{
rng.seed(seed_val);
}
现在我们可以创建发行版:
std::uniform_int_distribution<uint32_t> uint_dist; // by default range [0, MAX]
std::uniform_int_distribution<uint32_t> uint_dist10(0,10); // range [0,10]
std::normal_distribution<double> normal_dist(mean, stddeviation); // N(mean, stddeviation)
…并使用引擎创建随机数!
while (true)
{
std::cout << uint_dist(rng) << " "
<< uint_dist10(rng) << " "
<< normal_dist(rng) << std::endl;
}
并发
选择<random>
而不是传统的rand()
的另一个重要原因是,现在如何使随机数生成线程安全非常清楚和明显:要么为每个线程提供自己的线程本地引擎,在线程本地种子上播种,要么同步访问引擎对象。
Misc
- 一篇关于TR1随机的有趣文章。维基百科有一个很好的总结(谢谢,@Justin)。
- 原则上,每个引擎都应该定义一个
result_type
类型,这是种子使用的正确的整型。我认为我曾经有一个错误的实现,迫使我在x64上强制std::mt19937
到uint32_t
的种子,最终这应该是固定的,你可以说MyRNG::result_type seed_val
,从而使引擎非常容易更换。
随机数生成器是一个方程,给定一个数字,它会给你一个新数字。通常,您要么提供第一个数字,要么从系统时间等内容中提取。
每次请求一个新数字时,它都会使用前一个数字来执行方程。
如果一个随机数生成器倾向于比其他数字更频繁地产生相同的数字,那么它就不被认为是非常好的。例如,如果你想要一个1到5之间的随机数,并且你有这样的数字分布:
- 1:1 %
- 2: 80%
- 3:5 %
- 4:5 % <
- 5: 9%/gh>
2比其他任何数字产生的频率都要高,因此它比其他数字更有可能产生。如果所有的数字都是相等的你每次都有20%的机会得到每个数字。换句话说,上述分布非常不均匀,因为2更受青睐。所有20%的分布都是均匀的。
通常,如果你想要一个真正的随机数,你会从天气或其他自然来源中提取数据,而不是从随机数生成器中提取数据。
- 函数何时会在c++中包含stack_Unwind_Resume调用
- Python中的for循环与C++有何不同
- 在C++中释放内存期间,迭代器与指针有何不同
- 标准对此指向成员函数类型模板参数有何说明?是我的代码有误,还是 MSVS 16.6 有问题?
- 类中的 C++ int 被设置为值,似乎不知从何而来
- -fvisibility-inline-hidden 与 gcc 中的 -fvisibility=hidden 有何不同
- 使用程序生成来创建磁盘,但纹理无法正常工作
- G++ 在生成文件中使用时停止工作
- 如何使用模板生成整数序列在这里工作
- 收益率和回报有何不同?
- 覆盖私有功能,它与受保护功能有何不同?
- 无法使用 Visual Studio 启动 DirectX 11 可执行文件,生成工作正常
- 擦除删除成语的性能增益从何而来
- 无论代码长度如何,以下代码的内存要求有何不同?
- "virtual"对C++析构函数有何影响?
- 如果我对"while"块发表评论,为什么程序会死机?其中的"yield"线有何影响?
- 不更改生成文件后,生成文件项目不会生成(几乎相同的生成,工作正常)
- 当 int 方法工作正常时,void 方法有何不同,或者为什么我不能调用 void 方法?
- 无法使我的生成文件工作
- 我如何让这个c++程序生成一个工作的wav文件