如何在 class 中重用和重新初始化 c++ discrete_distribution?
How to reuse and reinitialize c++ discrete_distribution in class?
我正在用 C++ class 编写离散分布随机数生成器。要求是:
- 我不想在每次使用时都创建一个 discrete_distribution 对象。我知道分布对象是轻量级的,但是我的权重数组太长了,成本还是太高了。另外,我需要在这个 class.
的不同函数中使用分布对象
- 我需要不时更改分布(权重数组)
- 我不知道构造class时的确切分布(权重数组)
目前我有两个解决方案,在 class 中使用 random_device rd; mt19937 engine;
和初始化列表中的 engine(rd())
初始化随机数引擎后。
一种是用discrete_distribution<> *d=new discrete_distribution<>(weight_array,weight_array+weight_array_size)
创建discrete_distribution对象,并将指针存储在class中。每次我调用 (*d)(engine) 生成一个随机数,我只需要删除分布并重新生成一个来更新权重数组。
另一种方法是在class中定义discrete_distribution<> d
并用d=discrete_distribution<>(weight_array,weight_array+weight_array_size)
更新权重数组,这样我们就可以用d(engine)
生成随机数而不需要担心指针。
但这两种方式似乎都不是 class使用 C++ 对象的正确方式。他们错了吗?这样写代码有什么缺点吗?
谢谢
Another way is to define discrete_distribution<> d
in class and update weight array with d=discrete_distribution<>(weight_array,weight_array+weight_array_size)
, so that we can generate random number with d(engine)
and don't need to worry about pointers.
这是处理对象实例的完美通用 C++ 风格。
事实上,许多类型没有修饰符成员,因为它们是可赋值的。
在这种情况下,您可以使用 params()
成员来更改权重:
#include <boost/random.hpp>
#include <boost/random/random_device.hpp>
#include <boost/range/algorithm/copy.hpp>
#include <iostream>
namespace br = boost::random;
struct X {
using Weight = double;
br::mt19937 engine { br::random_device{}() };
br::discrete_distribution<int, Weight> dist { {0.2, 0.2, 0.2, 0.2, 0.2} };
void sample() {
for (auto i : {1,2,3,4})
std::cout << "#" << i << ":" << dist(engine) << " ";
std::cout << "\n";
}
void show_probabilities() {
boost::copy(dist.param().probabilities(), std::ostream_iterator<Weight>(std::cout << "probabilities: ", " "));
std::cout << "\n";
}
void reprogram(std::initializer_list<Weight> probabilities) {
dist.param(probabilities);
}
};
int main() {
X x;
x.show_probabilities();
x.sample();
x.reprogram({0.01, 0.99});
x.show_probabilities();
x.sample();
}
正在打印类似
的内容
probabilities: 0.2 0.2 0.2 0.2 0.2
#1:1 #2:2 #3:0 #4:4
probabilities: 0.01 0.99
#1:1 #2:1 #3:1 #4:1
我正在用 C++ class 编写离散分布随机数生成器。要求是:
- 我不想在每次使用时都创建一个 discrete_distribution 对象。我知道分布对象是轻量级的,但是我的权重数组太长了,成本还是太高了。另外,我需要在这个 class. 的不同函数中使用分布对象
- 我需要不时更改分布(权重数组)
- 我不知道构造class时的确切分布(权重数组)
目前我有两个解决方案,在 class 中使用 random_device rd; mt19937 engine;
和初始化列表中的 engine(rd())
初始化随机数引擎后。
一种是用discrete_distribution<> *d=new discrete_distribution<>(weight_array,weight_array+weight_array_size)
创建discrete_distribution对象,并将指针存储在class中。每次我调用 (*d)(engine) 生成一个随机数,我只需要删除分布并重新生成一个来更新权重数组。
另一种方法是在class中定义discrete_distribution<> d
并用d=discrete_distribution<>(weight_array,weight_array+weight_array_size)
更新权重数组,这样我们就可以用d(engine)
生成随机数而不需要担心指针。
但这两种方式似乎都不是 class使用 C++ 对象的正确方式。他们错了吗?这样写代码有什么缺点吗?
谢谢
Another way is to define
discrete_distribution<> d
in class and update weight array withd=discrete_distribution<>(weight_array,weight_array+weight_array_size)
, so that we can generate random number withd(engine)
and don't need to worry about pointers.
这是处理对象实例的完美通用 C++ 风格。
事实上,许多类型没有修饰符成员,因为它们是可赋值的。
在这种情况下,您可以使用 params()
成员来更改权重:
#include <boost/random.hpp>
#include <boost/random/random_device.hpp>
#include <boost/range/algorithm/copy.hpp>
#include <iostream>
namespace br = boost::random;
struct X {
using Weight = double;
br::mt19937 engine { br::random_device{}() };
br::discrete_distribution<int, Weight> dist { {0.2, 0.2, 0.2, 0.2, 0.2} };
void sample() {
for (auto i : {1,2,3,4})
std::cout << "#" << i << ":" << dist(engine) << " ";
std::cout << "\n";
}
void show_probabilities() {
boost::copy(dist.param().probabilities(), std::ostream_iterator<Weight>(std::cout << "probabilities: ", " "));
std::cout << "\n";
}
void reprogram(std::initializer_list<Weight> probabilities) {
dist.param(probabilities);
}
};
int main() {
X x;
x.show_probabilities();
x.sample();
x.reprogram({0.01, 0.99});
x.show_probabilities();
x.sample();
}
正在打印类似
的内容probabilities: 0.2 0.2 0.2 0.2 0.2
#1:1 #2:2 #3:0 #4:4
probabilities: 0.01 0.99
#1:1 #2:1 #3:1 #4:1