使用rand()强制惟一的有效方法是什么?
What is an efficient method to force uniqueness using rand();
如果我使用(带适当的#includes)
int main()
{
srand(time(0));
int arr[1000];
for(int i = 0; i < 1000; i++)
{
arr[i] = rand() % 100000;
}
return 0;
}
要生成随机的5位ID号(这里忽略omanip的东西),rand()
是否保证这些ID号是唯一的?我一直在运行另一个循环来检查数组的所有值与最近生成的ID号,但考虑到嵌套的1000个迭代循环,它需要永远运行。顺便问一下,有什么简单的方法来检查吗?
由于问题标记为c++11,
你应该考虑用<random>
代替rand()
。
使用一个标准的分发引擎,你不能保证你会得到唯一的值。如果你使用的是std::set
,你可以一直尝试,直到你有合适的量。根据您的分布范围和您请求的惟一值的数量,这可能就足够了。
例如,下面是一个自定义函数,用于从[x,y]
范围中获取n
唯一值。
#include <unordered_set>
#include <iostream>
#include <random>
template <typename T>
std::unordered_set<T> GetUniqueNumbers(int amount, T low, T high){
static std::random_device random_device;
static std::mt19937 engine{random_device()};
std::uniform_int_distribution<T> dist(low, high);
std::unordered_set<T> uniques;
while (uniques.size() < amount){
uniques.insert(dist(engine));
}
return uniques;
}
int main(){
//get 10 unique numbers between [0,100]
auto numbers = GetUniqueNumbers(10,0,100);
for (auto number: numbers){
std::cout << number << " ";
}
}
不能,因为任何对随机源输出的保证都会降低其随机性。
有一些特定的数学公式具有称为随机排列的行为。这个网站似乎有相当好的关于它的文章:http://preshing.com/20121224/how-to-generate-a-sequence-of-unique-random-integers/
不,绝对不能保证rand
不会产生重复的数字,以这种方式设计它不仅要记住它迄今为止返回的所有数字,而且还会大大降低它的随机性(在它返回了许多数字之后,你可以从它迄今为止已经返回的数字中猜测它可能返回的是什么)。
如果惟一性是您的唯一目标,只需为每件事使用一个递增的ID号。如果数字也必须是任意的并且难以猜测,则必须使用某种随机生成器或散列,但应该使数字更长,以使碰撞的机会更接近于0。
然而,如果你绝对必须这样做,我建议将你迄今为止生成的所有数字存储到std::unordered_map
中,并生成另一个随机数,如果它已经在其中。
在大多数prng中都有一个通用的唯一性保证,但在这里它对您没有帮助。生成器通常会迭代有限数量的状态,并且不会访问相同的状态两次,直到每个其他状态都访问了一次。
然而,状态和你看到的数字是不一样的。许多状态可以映射到相同的数字,在最坏的情况下,两个连续的状态可以映射到相同的数字。
也就是说,有一些特定的PRNG配置可以在重新访问旧状态之前访问指定范围内的每个值。值得注意的是,如果LCG设计的模量是您的范围的倍数,则可以通过另一次模操作将其缩小到与您的范围完全相同。由于大多数LCG实现具有2次幂周期,这意味着低阶位以较短的周期重复。然而,10000不是2的幂,所以这对你没有帮助。
一个简单的方法是使用LCG,将其位掩码降低到比期望范围大2的幂次,然后丢弃超出范围的结果。
- 在C++中初始化向量映射的最有效方法
- 将此布尔值传递给此函数的最有效方法是什么?
- 比较C++变量的最有效方法
- 在 c++ 中解决段树以外的范围查询的有效方法是什么?
- 存储变量的更有效方法是什么?
- 确保套装新鲜度的有效方法
- 当映射包含字符串向量作为值时,从值中获取键的有效方法
- 映射唯一值和重复值的有效方法.可以访问键或值的位置
- 在C++事务之间存储大量字符数据的有效方法
- 在unordered_multimap中精确迭代一次每个键的有效方法
- 一种将 Dart 中的字节数据转换为 C++ 中的无符号字符*的有效方法?
- 检查两个向量是否并行的最有效方法
- 从浮点数中删除小数部分但保留类型的有效方法
- 传递非泛型函数的最有效方法是什么?
- 按升序打印矢量的所有元素直到它为空而没有重复项的最有效方法是什么?
- 创建字符串数组的有效方法
- 返回一个引用C++中另一个类对象的对象的有效方法
- C++去除前x个元素的有效方法,在不改变向量大小的情况下将第x+1个元素推到第一个
- 将一种数据类型的向量复制到同一数据类型的结构向量中的有效方法是什么
- 从std::map值中获取密钥的有效方法