我正在尝试创建一些生成随机数组且没有重复值的内容。我已经看过其他答案,但似乎没有人帮助我理解。我想不出一种方法来实际生成不包含重复项的随机数。这是我到目前为止所尝试的:
srand(time(NULL));
int numbers [4];
for (int x=0; x!=4;x++)
{
numbers[x] = 1 + (rand() % 4) ;
printf("%d ", numbers[x]);
}
任何帮助将不胜感激。
答案 0 :(得分:16)
您开始使用从0
std::iota(begin(vec), end(vec), 0);
然后你给自己一个像样的随机数生成器并正确播种
std::mt19937 rng(std::random_device{}());
最后你使用rng
来改变元素 std::shuffle(begin(vec), end(vec), rng);
在某些实现中,random_device
无法正常工作(最明显的是Windows上的gcc),您必须使用替代种子,即当前时间→chrono
。
答案 1 :(得分:6)
首先,rand()
是一个随机数字,但不是重复的。
如果要生成随机数组没有重复项,rand()
方法根本无效。
假设您要生成 1000个数字的数组。在最好的情况下,假设您生成了没有重复的前999个数字,并且最后认为要做的是生成 最后一个数字。 获得该数字的概率是1/1000 所以这几乎需要永远生成。实际上只有10个数字会造成很大麻烦。
最好的方法是通过增量生成所有数字(或严格单调序列) shuffle 。在这种情况下,会有没有重复
Here是关于如何使用10个数字的例子。即使有1000个数字,它也是working。
注意:来自Jhon Leehey的answer的补课功能。
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
void shuffle(int *arr, size_t n)
{
if (n > 1)
{
size_t i;
srand(time(NULL));
for (i = 0; i < n - 1; i++)
{
size_t j = i + rand() / (RAND_MAX / (n - i) + 1);
int t = arr[j];
arr[j] = arr[i];
arr[i] = t;
}
}
}
int main()
{
int i;
int arr[10];
for (i=0; i<10; i++){
arr[i] = i;
}
shuffle(arr, 10);
for (i=0; i<10; i++){
printf("%d ", arr[i]);
}
}
答案 2 :(得分:2)
有两种解决方案可供选择:
使用rand()等内容生成随机数并检查重复项。
找到一个严格单调(最好是严格增加)的数学序列,并将其术语作为数组的成员。然后,您可以随机播放阵列。结果不是真正随机的,但是使用rand()都不会。 rand()使用了一个simillar tehnique,这就是为什么我们需要设置一些改变的种子,就像时间一样。例如,您可以使用时间来生成序列的第一个元素,并且使用良好的序列,您的结果至少是合适的。请注意,序列必须严格单调,以避免产生重复。序列不需要太复杂。例如,如果你得到unix time模10000作为第一项,那么你使用像x [i] = x [i-1] + 3 * x [i-2]这样的重复生成其他术语应该没问题。当然,你也可以使用更复杂的序列,但是在溢出时要小心(因为你不能对结果应用模运算符,因为它不会再增加)和你想要的数字位数。
答案 3 :(得分:1)
srand(time(NULL));
const int N = 4;
int numbers [N];
bool isAlreadyAdded(int value, int index)
{
for( int i = 0; i < index; i ++)
if( numbers[i] == value)
return true;
return false;
}
for (int x=0; x!=N;x++)
{
int tmp = 1 + (rand() % N) ;
while( x !=0 && isAlreadyAdded(tmp, x))
tmp = 1 + (rand() % N) ;
numbers[x] = tmp;
printf("%d ", numbers[x]);
}
这只是一种方式。它应该工作,当然有更好的方法
答案 4 :(得分:0)
在c ++中,您只需要:
std::random_shuffle()
http://www.cplusplus.com/reference/algorithm/random_shuffle/
int numbers [4];
for (int x=0; x!=4;x++)
{
numbers[x] = x;
}
std::random_shuffle(numbers, numbers +4);
更新:好的,我一直在想一个合适的地图功能可以从每个索引转到一个随机数,但再想一想我意识到这可能很难。以下应该有效:
int size = 10;
int range = 100;
std::set<int> sample;
while(sample.size() != size)
sample.insert(rand() % range); // Or whatever random source.
std::vector<int> result(sample.begin(), sample.end());
std::random_shuffle ( result.begin(), result.end() );
答案 5 :(得分:0)
您可以使用自己的随机数生成器,其序列大于或等于数组的长度。有关说明,请参阅http://en.wikipedia.org/wiki/Linear_congruential_generator#Period_length。
所以你需要LCG,表达式Xn + 1 =(aXn + c)mod m。值m必须至少与数组的长度一样大。检查“是否且仅当”最大序列长度的条件,并确保您的数字满足它们。
因此,您将能够为大多数用途生成具有令人满意的随机性的随机数,这保证在前m次调用中不会重复任何数字。
答案 6 :(得分:0)
生成每个随机数后,循环显示先前的值并进行比较。如果匹配,请重新生成新值并重试。
答案 7 :(得分:0)
这个怎么样:
#define NUMS (10)
int randomSequence[NUMS] = {0}, i = 0, randomNum;
bool numExists[NUMS] = {false};
while(i != NUMS)
{
randomNum = rand() % NUMS;
if(numExists[randomNum] == false)
{
randomSequence[i++] = randomNum;
numExists[randomNum] = true;
}
}
当然,NUMS
越大,执行while
循环所需的时间就越长。
答案 8 :(得分:0)
如果你想伪随机遍历大空间而不维护访问索引,你应该看看我多年前为基本技术做出贡献的这个项目。 http://packetfactory.openwall.net/projects/ipspace/index.html
您应该能够根据自己的目的进行调整,来源位于页面底部。