我制作了一个生成随机数组的程序。我知道如果我使用for
结构来放置随机数,我可能会有重复的值。为此,我创建了一个单独的递归函数,一直在查找重复项并将其替换为其他值,直到只有不同的数字:
#include <iostream>
#include <stdlib.h>
#include <time.h>
using namespace std;
int n, m, k, row[100];
int verif(int v[100], int k)
{
for(int i=0; i<k-1; i++)
for(int j=i+1; j<k; j++)
if(v[i]==v[j])
{
cout<<".";
srand(time(NULL));
v[i]=rand()%100+1;
return verif(v, k);
}
return 1;
}
int main()
{
k=10, n=10;
srand(time(NULL));
row[0]=rand()%n+1;
srand(row[0]);
for(int i=1; i<k; i++)
{
srand(row[i-1]);
row[i]=rand()%n+1;
}
verif(row, k);
for(int i=0; i<k; i++)
cout<<row[i]<<" ";
return 0;
}
我希望你能解释一下为什么一个简单的cout
在verif
里面使我的程序工作,为什么没有它就没有用。
答案 0 :(得分:4)
这是在一段延长的时间内递归调用函数的结果,可能会触发您机器上的堆栈溢出。
此表达式
srand(time(NULL));
将rand()
的随机数生成器播种到自纪元以来的当前秒数的值。当然这个数字每秒只改变一次。重新设定rand
生成器将获得与上次相同的序列,因此在rand()%100 + 1
的结果发生更改之前,以下行中time(NULL)
的结果将保持不变。
既然你已经确保v[i]==v[j]
将是true
,直到自初始分配起至少经过一秒钟,你再次递归调用此函数,(并再次......) ))直到你从“随机”数字生成过程中获得一个新值(至少已经过了一秒)或者你的堆栈空间不足。 (你崩溃了)
通过使用一个比cout
语句更长的执行时间的函数,你可以清楚地看到这种情况发生的更明显,例如
std::this_thread::sleep_for(std::chrono::milliseconds{500});
您可以在on coliru
看到这样的效果使用休眠函数(每次递归持续执行500毫秒),你会得到~13次递归。
没有它你会得到~2846000递归。这是非常不同的。
有更好的方法可以获得范围内的一组非重复随机数,如this question的答案所示。我自己偏爱Darklighter的回答。对于那个答案,如果你想要,比如100个中的10个元素,生成带有100个元素的向量,随机播放,然后调整它以仅包含前10个元素。
答案 1 :(得分:1)
cout
解决了这个问题,因为在控制台上打印内容需要时间。所有其余代码大约需要0次,因此每次执行
srand(time(NULL));
v[i]=rand()%100+1;
您将获得完全相同的数字,因为您始终使用相同的种子。然后我不是100%确定会发生什么,它可能是一个stackoverflow因为你一直在递归地调用函数,或者它可能是其他东西。实际上它并不重要,因为真正的问题是你的种子。
只有使用cout
,您才能获得不同的种子和不同的随机数。
你应该只播种一次rng。顺便说一句,如果你想要随机数,你应该使用<random>
而不是rand
的rng(实际上它应该被弃用,因为它的质量很低)。