我想在特定范围内生成随机数,并确保每个新数字都不是以前的重复项。一种解决方案是将以前生成的数字存储在容器中,每个新数字检查容器。如果容器中有这样的数字,则我们再次生成,否则我们使用并将其添加到容器中。但是,随着每个新数字的出现,此操作变得越来越慢。是否有更好的方法或任何可以更快地工作并确保生成独特性的rand函数?
编辑:是的,有一个限制(例如从0到10亿)。但我想生成100,000个唯一数字!(如果解决方案使用Qt功能将非常好。)
我想在特定范围内生成随机数,并确保每个新数字都不是以前的重复项。一种解决方案是将以前生成的数字存储在容器中,每个新数字检查容器。如果容器中有这样的数字,则我们再次生成,否则我们使用并将其添加到容器中。但是,随着每个新数字的出现,此操作变得越来越慢。是否有更好的方法或任何可以更快地工作并确保生成独特性的rand函数?
编辑:是的,有一个限制(例如从0到10亿)。但我想生成100,000个唯一数字!(如果解决方案使用Qt功能将非常好。)
这些随机数有范围限制吗?如果你有一个随机数的限制,并且你一直生成唯一的随机数,那么你最终会得到一个 x..y 范围内所有数字的随机排序列表,其中 x-y 是你的随机数的有效范围。如果是这种情况,你可以通过生成 x..y 中所有数字的列表并进行洗牌来大大提高速度,而不是生成数字。
我认为根据范围大小和所需的性能模式,有三种可能的方法可以使用另一种算法。
根据所需速度,您可以将所有列表存储在数据库中。除了速度外,它们无需保存在内存中。
填写一个数字列表,然后将列表洗牌并从一端选择您需要的数字。
我认为有一类伪随机数生成器具有您想要的特性:线性同余生成器。如果正确定义,它将产生一个整数列表从0到N-1,在使用完列表中所有数字之前不会重复出现两个数字。
#include <stdint.h>
/*
* Choose these values as follows:
*
* The MODULUS and INCREMENT must be relatively prime.
* The MULTIPLIER-1 must be divisible by all prime factors of the MODULUS.
* The MULTIPLIER-1 must be divisible by 4, if the MODULUS is divisible by 4.
*
* In addition, modulus must be <= 2**32 (0x0000000100000000ULL).
*
* A small example would be 8, 5, 3.
* A larger example would be 256, 129, 251.
* A useful example would be 0x0000000100000000ULL, 1664525, 1013904223.
*/
#define MODULUS (0x0000000100000000ULL)
#define MULTIPLIER (1664525)
#define INCREMENT (1013904223)
static uint64_t seed;
uint32_t lcg( void ) {
uint64_t temp;
temp = seed * MULTIPLIER + INCREMENT; // 64-bit intermediate product
seed = temp % MODULUS; // 32-bit end-result
return (uint32_t) seed;
}
您需要做的就是选择一个模数,使其大于您在给定运行中所需的数字数量。
unsigned int N = 1000;
vector <unsigned int> vals(N);
for(unsigned int i = 0; i < vals.size(); ++i)
vals[i] = i;
std::random_shuffle(vals.begin(), vals.end());
unsigned int random_number_1 = vals[0];
unsigned int random_number_2 = vals[1];
unsigned int random_number_3 = vals[2];
//etc
如果有这样的模式,那么它就不是随机的了吗?
据我所知,您需要存储并过滤所有不需要的数字...