我想从相对较大的人口中抽取n个样本而无需替换。因此,我绘制随机数字并跟踪我之前的选择,因此每当我绘制两次数字时,我都可以重新采样:
boost::mt19937 generator;
boost::uniform_int<> distribution(0, 1669 - 1);
boost::variate_generator<boost::mt19937, boost::uniform_int<> >
gen(generator, distribution);
int n = 100;
std::vector<int> idxs;
while(static_cast<int>(idxs.size()) < n)
{
// get random samples
std::generate_n(std::back_inserter(idxs), n - idxs.size(),
gen);
// remove duplicates
// keep everything that's not duplicates to save time
std::sort(idxs.begin(), idxs.end());
std::vector<int>::iterator it = std::unique(idxs.begin(), idxs.end());
idxs.resize(std::distance(idxs.begin(), it));
}
不幸的是,我遇到了上面使用的常量的无限循环。
我添加了一些输出(显示它一直选择相同的数字)并在10次尝试后停止显示问题:
boost::mt19937 generator;
boost::uniform_int<> distribution(0, 1669 - 1);
boost::variate_generator<boost::mt19937, boost::uniform_int<> >
gen(generator, distribution);
int n = 100;
int repeat = 0;
std::vector<int> idxs;
while(static_cast<int>(idxs.size()) < n)
{
if(repeat++ > 10) break;
cout << "repeat " << repeat <<
", " << idxs.size() << " elements" << endl;
std::generate_n(std::back_inserter(idxs), n - idxs.size(),
gen);
cout << "last " << idxs.back() << endl;
std::sort(idxs.begin(), idxs.end());
std::vector<int>::iterator it = std::unique(idxs.begin(), idxs.end());
idxs.resize(std::distance(idxs.begin(), it));
}
代码打印
repeat 1, 0 elements
last 1347
repeat 2, 99 elements
last 1359
repeat 3, 99 elements
last 1359
等等,如果我不杀死程序,这似乎永远循环。这不应该发生,对吧?我只是不走运?或者我做错了什么?
简短解决方案 感谢@jxh!使用参考有助于:
boost::variate_generator<boost::mt19937&, boost::uniform_int<> >
gen(generator, distribution);
答案 0 :(得分:1)
问题是generate_n
会创建您创建的生成器gen
的副本。因此,在调用generate_n
的最后,gen
的状态保持不变。因此,每次重新循环时,您将再次生成相同的序列。
解决此问题的一种方法是在variate_generator
中使用对随机数生成器对象的引用: *
boost::variate_generator<boost::mt19937&, boost::uniform_int<> >
gen(generator, distribution);
*由于我对Boost的经验有限,我的原始建议相当笨拙。我在这个答案中采用了提问者实施的解决方案。