C++;:如何在从给定缓存中排除数字的同时生成随机数 P> >在C++中,我使用MT1937 引擎< /强>和我的随机数生成器中的均匀分布> >: #include <random> #include <time.h> int get_random(int lwr_lm, int upper_lm){ std::mt19937 mt(time(nullptr)); std::uniform_int_distribution<int> dist(lwr_lm, upper_lm); return dist(mt); } #包括 #包括 int-get\u-random(int-lwr\u-lm,int-upper\u-lm){ 标准:mt19937 mt(时间(空PTR)); 标准:统一内部分布区(lwr-lm,上部lm); 返回区(mt); }

C++;:如何在从给定缓存中排除数字的同时生成随机数 P> >在C++中,我使用MT1937 引擎< /强>和我的随机数生成器中的均匀分布> >: #include <random> #include <time.h> int get_random(int lwr_lm, int upper_lm){ std::mt19937 mt(time(nullptr)); std::uniform_int_distribution<int> dist(lwr_lm, upper_lm); return dist(mt); } #包括 #包括 int-get\u-random(int-lwr\u-lm,int-upper\u-lm){ 标准:mt19937 mt(时间(空PTR)); 标准:统一内部分布区(lwr-lm,上部lm); 返回区(mt); },c++,random,C++,Random,我需要的是修改上面的生成器,以便在反复使用上面的生成器时,有一个缓存包含许多需要排除的整数。 如何更改上述内容以实现此目的?有很多方法。一个简单的方法是在std::set中维护“排除的数字”,在每次生成一个随机数后,检查它是否在集合中,如果在集合中,则生成一个新的随机数-重复,直到得到一个不在集合中的数字,然后返回该数字 顺便说一句;虽然发行版的构建成本很低,但引擎却不是。您不希望每次调用函数时都重新构造mt19937,而是创建一次,然后重新使用它。您可能还希望使用比当前时间(以秒为单位)更好的

我需要的是修改上面的生成器,以便在反复使用上面的生成器时,有一个缓存包含许多需要排除的整数。
如何更改上述内容以实现此目的?

有很多方法。一个简单的方法是在
std::set
中维护“排除的数字”,在每次生成一个随机数后,检查它是否在集合中,如果在集合中,则生成一个新的随机数-重复,直到得到一个不在集合中的数字,然后返回该数字


顺便说一句;虽然发行版的构建成本很低,但引擎却不是。您不希望每次调用函数时都重新构造
mt19937
,而是创建一次,然后重新使用它。您可能还希望使用比当前时间(以秒为单位)更好的种子。

这可能不是最漂亮的解决方案,但是什么阻止您在返回之前维护缓存和检查存在性?不过,对于大型缓存,速度会减慢

    #include <random>
    #include <time.h>
    #include <set>

    std::set<int> cache;

    int get_random(int lwr_lm, int upper_lm){

    std::mt19937 mt(time(nullptr));
    std::uniform_int_distribution<int> dist(lwr_lm, upper_lm);

    auto r = dist(mt);

    while(cache.find(r) != cache.end())
       r = dist(mt);

    return r;
}
#包括
#包括
#包括
std::设置缓存;
int-get\u-random(int-lwr\u-lm,int-upper\u-lm){
标准:mt19937 mt(时间(空PTR));
标准:统一内部分布区(lwr-lm,上部lm);
自动r=距离(mt);
while(cache.find(r)!=cache.end())
r=距离(mt);
返回r;
}
您1)是否试图在离散时间间隔内不更换样品?或者说,这段时间间隔内的零散分布是相当恒定的吗

如果1)您可以根据这里的答案使用std::shuffle


如果2)您可以使用std::discrete_distribution(元素0对应于
lwr_lm
),并将不需要的数字加权为零。显然,在
upper_lm-lwr_lm
中,内存需求是线性的,因此,如果内存需求很大,则可能不太实际,

,正如@virgesmith在他的回答中所提到的,这可能是解决问题的更好办法。
使用缓存并使用它来过滤未来生成的方法在大范围内效率低下

在这里,我用一种不同的方法写了一个简单的例子,但是你会受到你的记忆的限制。为缓冲区选取随机数,并在下一次迭代中将其删除

#include <random>
#include <time.h>
#include <iostream>

int get_random(int lwr_lm, int upper_lm, std::vector<int> &buff, std::mt19937 &mt){
  if (buff.size() > 0) {
    std::uniform_int_distribution<int> dist(0, buff.size()-1);
    int tmp_index = dist(mt);
    int tmp_value = buff[tmp_index];
    buff.erase(buff.begin() + tmp_index);
    return tmp_value;
  } else {
    return 0;
  }
}

int main() {
  // lower and upper limit for random distribution
  int lower = 0;
  int upper = 10;

  // Random generator
  std::mt19937 mt(time(nullptr));

 // Buffer to filter and avoid duplication, Buffer contain all integer between lower and uper limit
  std::vector<int> my_buffer(upper-lower);
  std::iota(my_buffer.begin(), my_buffer.end(), lower);

  for (int i = 0; i < 20; ++i) {
    std::cout << get_random(lower, upper, my_buffer, mt) << std::endl;
  }

  return 0;
} 
#包括
#包括
#包括
int-get_-random(int-lwr_-lm,int-upper_-lm,std::vector&buff,std::mt19937&mt){
如果(buff.size()>0){
标准::统一分布区(0,buff.size()-1);
int tmp_指数=距离(mt);
int tmp_值=buff[tmp_索引];
buff.erase(buff.begin()+tmp_索引);
返回tmp_值;
}否则{
返回0;
}
}
int main(){
//随机分布的上下限
整数下限=0;
整数上限=10;
//随机发生器
标准:mt19937 mt(时间(空PTR));
//缓冲区用于过滤和避免重复,缓冲区包含下限和上限之间的所有整数
std::向量my_缓冲区(上下);
std::iota(my_buffer.begin()、my_buffer.end()、lower);
对于(int i=0;i<20;++i){

std::cout我会为这个问题提出两个类似的解决方案。它们基于概率结构,并为您提供“可能在缓存中”或“肯定不在缓存中”的答案。有误报,但没有误报

  • 。有很多实现,包括。基本上,在一组缓存值上运行它,并使用生成的完美哈希函数拒绝采样值。您甚至不需要维护哈希表,只需要将随机值映射到整数索引。只要索引在哈希范围内,就拒绝该数字。完美意味着您只需要一次呼叫检查,结果将告诉您号码在集合中。存在潜在冲突,因此可能出现误报

  • 。同样的想法,使用每个缓存项中您愿意保留的任何位构建过滤器,通过快速检查,您将得到“缓存中可能存在的”答案或清除否定。您可以用答案精度换取内存,反之亦然。可能会出现误报


  • 我明白了,但我不明白的是如何使用上面提到的给定模块,我知道如何使用普通的“rand()”,但不知道如何使用mt19937或均匀分布。@random_x_y_z请看我的答案。@random_x_y_z随机数是否来自
    rand()
    统一整数分布
    不应该改变任何关于检查一组要丢弃的数字的内容。你有一个数字,你有一组要检查的数字,你可能需要生成一个新的数字。生成数字的方法如何改变任何事情?我不明白为什么这会让你绊倒。甚至我也想到了d这样做!但是考虑到我的特殊问题,我担心使用越多,处理时间可能会呈指数级增长!我想,你的意思是有一个
    cache.insert(get_random())
    涉及某个地方?@random_x_y_z您使用它的程度无关紧要。额外的性能成本取决于缓存的大小。除了@JesperJuhl提到的性能成本是在每次调用中重新初始化生成器的一个缺点外,另一个缺点是在同一秒内多次调用将生成相同的n数字。在开始采样之前,缓存是众所周知的吗?基本上,每个样本数您必须多久更新一次缓存?另一个问题-您能否接受不完美的检查场景,即误报?如果“排除数字的缓存”如果是大的,那么bloom过滤器是一个很好的方法。但对于小的集合来说,它可能是过度杀伤力了。@JesperJuhl是的,它是。问题是如何与imp相处