Aru*_*mar 1 c++ random distribution unique range
问题:
我的数字范围是 1 到 20,000。我想对范围内 8 个不同数字的均匀分布进行 1000 次采样。每个分布不应有重复的数字。此外,1000 个分布中的每个分布都必须是唯一的(在对所有获得的分布进行字母顺序排序后,从技术上讲,没有两个分布应该具有相同的数字序列)。
我做了什么:
我遇到了std::uniform_int_distribution<int>C++ 11 标准。因此尝试以下代码来测试其在不同范围内的唯一性。
#include <iostream>
#include <random>
int main(int, char*[]) {
const int range_from = 0;
const int range_to = 20000;
std::random_device rand_dev;
std::mt19937 generator(rand_dev());
std::uniform_int_distribution<int> distr(range_from, range_to);
for(int i = 0; i < 1000; ++i){ //Iteration for maximum distributions
for (int j = 0; j < 8; ++j) //Iteration for random distribution generation
std::cout << distr(generator) << '\n';
}
}
Run Code Online (Sandbox Code Playgroud)
不同尝试获得的输出
Attempt 1: Attempt 2:
16102 6656
540 10316
8718 12251
18059 1254
10976 3982
18391 12857
14748 9253
12137 3335
Run Code Online (Sandbox Code Playgroud)
一些事实:
根据两次尝试,输出看起来是唯一的。我还意识到,可以有 20,000C8 = 20,000!/(8!x19,992!) 这样可能的分布,这些分布可以是唯一的(每个分布中没有相同的数字,并且当我们进行字母排序时没有重复的分布)。
我的问题:
这段代码真的能以当前的形式实现我想要做的事情吗?或者我应该做一些昂贵的验证过程,例如对每个发行版进行字母顺序排序,并将它们中的每一个记录在一个中,std::vector并检查发行版是否已经存在?
后一个过程非常昂贵并且需要大量的计算时间。您会建议任何替代/更好的方法吗?
如果您希望这 1000 组 8 个随机数是唯一的,那么您可以生成所需的所有值,将它们随机化,然后将随机集中的前 8000 个值作为您的 1000 组 8 个随机数。
int main()
{
const int range_from = 0;
const int range_to = 20000;
std::vector<int> values(range_to - range_from);
std::generate(values.begin(), values.end(), [value = range_from]() mutable { return value++; });
// values now has 0 to 20000
std::shuffle(values.begin(), values.end(), std::mt19937{std::random_device{}()});
// now it is a random order
values.resize(8000);
// now we have the 8000 random numbers in the range 0 to 20000
}
Run Code Online (Sandbox Code Playgroud)
在这种情况下,这并不算太浪费,但如果您的范围足够大并且您想要的组数足够小,您可能需要选择不同的解决方案。否则你会浪费很多空间。