因此,在c++中,我在随机数生成器中使用mt19937 engine和随机数生成器,如下所示:
#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);
}
我需要修改上面的生成器,这样当我一次又一次地使用上面的生成器时,缓存中包含了一些我需要排除的整数。我如何改变上面的内容才能做到这一点?
发布于 2018-08-12 23:40:21
正如@virgesmith所提到的,在他的回答中,这可能是你的问题的更好的解决方案。
具有缓存并使用它来过滤未来生成的方法对于大范围wiki是低效的。
这里我用不同的方法写了一个简单的例子,但是你会受到你的记忆力的限制。您选择随机数作为缓冲区,并在下一次迭代中删除它。
#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;
}
编辑:更干净的解决方案here
发布于 2018-08-12 22:56:27
有很多方法可以做到这一点。一种简单的方法是在std::set
中维护您的“排除的数字”,在每次生成随机数后,检查它是否在集合中,如果它在集合中,则生成一个新的随机数-重复,直到您获得一个不在集合中的数字,然后返回该数字。
顺便说一句,虽然发行版的构建成本很低,但引擎却不是。您不希望在每次调用函数时都重新构造mt19937
,而是创建一次,然后重用它。您可能还希望使用比当前时间(秒)更好的种子。
发布于 2018-08-12 23:09:22
您是否正在1)尝试在离散间隔内不进行替换的情况下采样?或者它是2)在区间上的斑块分布,说是相当恒定的?
如果1)您可以按照此处的答案使用std::shuffle How to sample without replacement using c++ uniform_int_distribution
如果2),你可以使用std::discrete_distribution (元素0对应于lwr_lm
),并将你不想要的数字加权为零。显然,在upper_lm-lwr_lm
中,内存需求是线性的,因此如果内存需求很大,则可能不切实际
https://stackoverflow.com/questions/51809909
复制相似问题