我想在c ++随机库中使用uniform_int_distribution。但是,它只进行替换采样,如下例所示。如何在没有替换的情况下进行采样?
#include <iostream>
#include <random>
int main()
{
std::default_random_engine generator;
std::uniform_int_distribution<int> distribution(1,4);
for(int i=0; i<4; ++i)
std::cout << distribution(generator) << std::endl;
return 0;
}
答案 0 :(得分:3)
使用std::shuffle
,例如,std::array<int>
或std::vector<int>
,初始化为{1, 2, 3, 4}
。
然后按顺序回读容器内容。
这将比绘制一个随机数具有更好的统计特性,只有在之前没有绘制它时才接受它。
答案 1 :(得分:1)
从c ++ 17开始,现在有一个标准库函数可以完全做到这一点。参见https://en.cppreference.com/w/cpp/algorithm/sample
#include <iostream>
#include <random>
#include <string>
#include <iterator>
#include <algorithm>
int main()
{
std::string in = "abcdefgh", out;
std::sample(in.begin(), in.end(), std::back_inserter(out),
5, std::mt19937{std::random_device{}()});
std::cout << "five random letters out of " << in << " : " << out << '\n';
}
答案 2 :(得分:0)
如果要对N
个均匀分布的整数进行采样而不用从[low, high)
范围内进行替换,则可以这样写:
std::vector<int> array(N); // or reserve space for N elements up front
auto gen = std::mt19937{std::random_device{}()};
std::ranges::sample(std::views::iota(low, high),
array.begin(),
N,
gen);
std::ranges::shuffle(array, gen); // only if you want the samples in random order
这里是demo。
这类似于Philip M's answer,但是从C ++ 20可以延迟生成输入范围。