gpt4 book ai didi

c++ - C++11 类 的分布如何转换底层生成器?

转载 作者:可可西里 更新时间:2023-11-01 18:05:57 25 4
gpt4 key购买 nike

以下代码的行为似乎并不直观:

#include <random>
#include <iostream>
using namespace std;

int main()
{

mt19937 MyGenerator(40);
auto gauss = normal_distribution<double>(0,1);
auto linear = uniform_real_distribution<double>(0,1);
cout << gauss(MyGenerator) << endl; //line a
cout << linear(MyGenerator) << endl; //line b
cout << gauss(MyGenerator) << endl;
}

运行这段代码给出输出

-0.816097
0.705030
0.303032.

如果现在交换 a 行和 b 行的顺序,则输出变为

 0.644008
0.338080
-0.639501.

很明显,前两个数字现在不同了,因为它们是由不同的分布产生的。然而,为什么第三个数字不同呢?以我的直觉,分布应该获取一个数字 c = MyGenerator() ,然后将其映射到特定范围内的随机数。随机数生成器将指向分配调用后数字序列中的下一个数字。那么,在这两种情况下,第三次调用的结果不应该相同吗?

另一个观察:向任一分布添加第四次调用实际上似乎重现了相同的数字。

最佳答案

libstdc++ 的 normal_distribution 实现使用 Marsaglia polar method .这种方法的有趣之处在于,每次传递都使用来自 URNG 的两个随机数来生成两个结果。

也就是说,对分布的第一次调用调用了 URNG 两次(可能更多次,因为它使用拒绝抽样,但是是偶数次)并返回一个结果;以下对分配的调用不会调用 URNG,但会返回保存的第二个结果。

这是一个 extract from the source code , 稍微重新格式化:

if (_M_saved_available)
{
_M_saved_available = false;
ret = _M_saved;
}
else
{
result_type x, y, r2;
do
{
x = result_type(2.0) * aurng() - 1.0;
y = result_type(2.0) * aurng() - 1.0;
r2 = x * x + y * y;
}
while (r2 > 1.0 || r2 == 0.0);

const result_type mult = std::sqrt(-2 * std::log(r2) / r2);
_M_saved = x * mult;
_M_saved_available = true;
ret = y * mult;
}

关于c++ - C++11 类 <random> 的分布如何转换底层生成器?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/25684323/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com