我是否应该保留随机分布对象实例,或者我可以总是重新创建它

Should I keep the random distribution object instance or can I always recreate it?

本文关键字:新创建 创建 我可以 或者 保留 是否 随机 分布 实例 对象      更新时间:2023-10-16

我有这样的代码:

static std::mt19937 rnd;
// ...
static uint32_t rndInt(uint32_t min, uint32_t max) {
    return std::uniform_int_distribution<uint32_t>(min,max)(rnd);
}

这是好的做法吗?还是我应该存储uniform_int_distribution ?

我怀疑创建和销毁分布对象的成本是否很高,尽管我认为它可能比仅仅存储参数min,max要稍微高一些。它可以根据参数预先计算出一些有用的值,例如,在明显的实现中,2**32 % (max-min+1)是来自生成器的不同值的数量,这些值将被丢弃并重新尝试。

原则上,允许分布对象在其内部存储一些熵位,这些熵位是在以前调用operator()时从生成器中提取的,但不是必需的。这些位可以用于以后的operator()调用。因此,如果min==0max==1,那么您可以在生成器上每次调用分布上的operator()调用32次。这就是reset()函数的作用,清除这种状态。

所以如果你重复使用相同的min/max值,那么从技术上讲,你每次使用一个新的分布都是在浪费随机比特——你可能会比保留分布对象更少地调用引擎。但我怀疑这有什么关系,特别是因为MT速度很快。

我通常这样做:

std::uniform_int_distribution<uint32_t> distrib(16, 97);

那么您可以多次调用distrib(rnd),而不必每次重新生成分布。

您执行操作的方式强制在每次调用时重新创建分布。如果您的最小和最大参数是固定的,那么创建一个分布对象并调用它,否则,保持现有的

顺便说一句,我会用time(NULL)或其他方法播种rnd

熵存储在std::mt19937中,这意味着您将继续随机序列,但正如Steve Jessop所指出的,它仍然有一些创建对象的开销。如果您希望使用相同的参数频繁调用此函数,那么您可以在使用std::pair<uint32_t, uint32_t>作为键的映射中缓存std::uniform_int_distribution<uint32_t>对象。