我正在尝试使用该函数discard来跳过随机数序列中的数字。这是我的尝试:
#include <random>
#include <iostream>
using namespace std;
int main ()
{
unsigned seed = 1;
uniform_real_distribution<> dis(0,10);
mt19937 gen (seed);
cout << dis(gen) << endl;
//gen.discard(1); // supposed to be the same of `dis(gen)`?
cout << dis(gen) << endl;
cout << dis(gen) << endl;
}
Run Code Online (Sandbox Code Playgroud)
这段代码的输出是
9.97185
9.32557
1.28124
Run Code Online (Sandbox Code Playgroud)
如果我取消注释该行,gen.discard(1)我会得到
9.97185
0.00114381
3.02333
Run Code Online (Sandbox Code Playgroud)
但我预计前两个数字是9.97185和1.28124,因为该数字9.32557将被跳过。
问:如何discard正确使用,或者有没有与我想要的效果相同的替代解决方案?我可以简单地使用dis(gen),但是还有其他方法吗?
在生成下一个结果时,分布可以多次调用生成器,因此为了获得所需的输出,您需要通过匹配的调用次数来推进生成器的状态。作为一个快速测试,如果我们装备自己的生成器来计算调用次数
struct my_mt19937 : mt19937
{
using mt19937::mt19937;
unsigned called = 0;
mt19937::result_type operator()()
{
++called;
return mt19937::operator()();
}
unsigned invocations()
{
auto result = called;
called = 0;
return result;
}
};
Run Code Online (Sandbox Code Playgroud)
然后用它代替
unsigned seed = 1;
uniform_real_distribution<> dis(0,10);
my_mt19937 gen (seed);
cout << dis(gen) << endl;
cout << gen.invocations() << endl;
cout << dis(gen) << endl;
cout << gen.invocations() << endl;
cout << dis(gen) << endl;
cout << gen.invocations() << endl;
Run Code Online (Sandbox Code Playgroud)
9.97185
2
9.32557
2
1.28124
2
Run Code Online (Sandbox Code Playgroud)
因此生成器被调用两次来生成每个结果。现在,如果我们将您的示例修改为 call gen.discard(2);,它会产生您期望的结果。
9.97185
1.28124
9.99041
Run Code Online (Sandbox Code Playgroud)
我不知道有一种可移植的方法来确定分布调用生成器的次数,因此放弃中间结果的最佳选择是调用dis(gen);并忽略该结果。
| 归档时间: |
|
| 查看次数: |
307 次 |
| 最近记录: |