c++11中在类中的不同方法之间共享random_number_engine
share random_number_engine between different methods within a class in c++11
我有一个类,在几个不同的成员方法中需要随机数。我使用的是C++11
,我认为在每种方法中新创建一个随机数生成器是不可行的。
是否有可能通过使其成为类的成员属性或类型定义来跨类共享随机数生成器,同时仍然确保良好的随机性?
我该怎么做呢,也许你可以给我举个小例子?我应该在哪里为随机引擎设置种子,我想使用具有不同类型分布的Mersenne twister
引擎(normal
&uniform
)。
引擎和分布都是值,可以像其他具有值类型的对象一样作为成员。
你应该在引擎被创建的时候播种,这意味着,如果它是一个成员,在你的对象被构造的时候播种。我的例子在默认情况下使用random_device
的类内初始化器来为引擎播种。它还允许指定种子,以获得可重复的、可测试的结果。
std::mt19937 make_seeded_engine() {
std::random_device r;
std::seed_seq seed{r(), r(), r(), r(), r(), r(), r(), r()};
return std::mt19937(seed);
}
struct Foo {
std::mt19937 eng = make_seeded_engine();
std::uniform_int_distribution<> dist1 {1, 20};
std::uniform_real_distribution<> dist2 {0.0, 100.0};
Foo() = default;
template<typename SeedSeq>
Foo(SeedSeq &&seed) : eng(seed) {}
int bar() {
return dist1(eng);
}
double baz() {
return dist2(eng);
}
};
您至少需要在使用之间存储引擎,因为保证随机序列均匀分布只适用于对同一引擎对象的重复调用序列。不能保证使用不同的引擎产生的序列。
实际上分布也是如此,尽管我不知道每次创建一个新的分布实际上会产生不正确的结果(有些实现中分布由于各种原因缓存值,但是,每次创建分布可能会表现得更差,并且产生不同的序列)。
例如,计算正态分布的常用算法一次产生两个值。`std::normal_distribution `的实现做到了这一点,并缓存第二个值以在每次其他调用时使用。下面的程序展示了这一点。
#include <iostream>
#include <random>
int main() {
typedef std::mt19937 Engine;
typedef std::normal_distribution<> Distribution;
Engine eng(1);
Distribution dist;
for (int i=0; i<10; ++i)
std::cout << dist(eng) << ' ';
std::cout << 'n';
eng.seed(1);
for (int i=0; i<10; ++i)
std::cout << Distribution()(eng) << ' ';
std::cout << 'n';
}
使用vc++ 2012,我得到输出:
0.156066 0.3064 -0.56804 -0.424386 -0.806289 -0.204547 -1.20004 -0.428738 -1.18775 1.30547
0.156066 -0.56804 -0.806289 -1.20004 -1.18775 -0.153466 0.133857 -0.753186 1.9671 -1.39981
请注意,每次迭代创建新分布时产生的序列只包含单个分布产生的序列的所有其他值。
是否有可能通过使其成为类的成员属性或类型定义来跨类共享随机数生成器,同时仍然确保良好的随机性?
绝对。如果您使用不同的种子初始化它(或让它使用默认值),则每次调用RNG时都应该获得"良好"的随机性。事实上,我建议为每种方法使用单独的RNG不仅成本高,而且是一个糟糕的设计。
关于如何实现各种发行版,http://en.cppreference.com/w/cpp/numeric/random有一些很好的例子(比如这个)。
- 将成员变量添加到共享库中的类中,不会破坏二进制兼容性吗
- 是否可以通过C++扩展强制多个python进程共享同一内存
- 在cuda线程之间共享大量常量数据
- 如何从具有移动语义的类对象中生成共享指针
- 在c代码之间共享数据的最佳方式
- 在两个类中共享相同的函数调用,并在不需要时避免空实例化
- 将静态库链接到不带-fPIC的共享库中
- 为什么std::互斥需要很长的、非常不规则的时间来共享
- 使用Boost Interprocess创建托管共享内存需要很长时间
- 无法在Ubuntu上将共享库与Eclipse链接
- 从python调用openMP共享库时,未定义opnMP函数
- 在为LINUX创建共享库时,如何避免STL的私有/弱副本
- 为什么我的共享库中存在展开符号
- 使用共享指针的函数调用,其对象应为 const
- 具有两个独占锁组的共享锁
- 共享队列的线程安全
- 共享指针和具有自定义删除程序的唯一指针之间的语法差异背后的任何原因
- 多个"常量引用"变量可以共享同一个内存吗?
- 如何访问由共享指针保存的类方法?
- 从矢量或地图中删除共享指针