C++生成1-9不重复随机数时出现无限循环问题咨询
问题描述
我尝试生成5个取值范围为1到9(包含两端边界值)的互不重复随机数。目前我仍在学习C++,仅掌握当前所用的这种随机数生成方法,对该语言的较新特性尚不熟悉,实现代码如下:
#include <iostream> #include <ctime> #include <cstdlib> void Generate(int arr[], const int size){ std::srand(std::time(0)); arr[0] = 1 + (std::rand() / ((1u + RAND_MAX) / 8)); int random; int counter; bool flag; for(int i = 1; i < size; ++i){ counter = 0; flag = true; while(flag){ random = 1 + (std::rand() / ((1u + RAND_MAX) / 8)); for(int j = 0; j < i; ++j){ if(arr[j] == random){ ++counter; } } if(!counter){ arr[i] = random; flag = false; } else{ std::cout << "false "; } } } } void Print(int const arr[], const int size){ for(int i = 0; i < size; ++i){ std::cout << arr[i] << ' '; } } int main() { constexpr int ksize = 5; int arr[ksize]; Generate(arr, ksize); Print(arr, ksize); return 0; }
上述代码有时可以正常运行,但多数场景下会触发无限循环。我在代码中添加了如下调试片段,作用是确认程序确实进入了无限循环状态:
else{ std::cout << "false "; }
故障原因
导致无限循环的核心bug是变量重置逻辑错误,附带还有两处逻辑问题:
- 核心致死原因:
counter变量未在重试循环内重置
你仅在for循环(为第i个位置选数)的入口处将counter初始化为0,但内部的while重试循环每跑一轮,都没有把counter清零。
实际运行时很容易出现这个场景:给第2个数组元素选值时,第一次生成的随机数和已存在的数重复,counter累加为1,进入else分支打印false后直接进入下一轮while循环。此时counter仍保留上一轮的1,哪怕新一轮生成的随机数完全不重复,遍历完已有元素后counter还是1,判断条件if(!counter)永远不成立,flag始终为true,程序直接卡死在while循环里。
只有极端情况——第一轮while循环生成的数刚好不重复,counter保持初始的0,程序才能正常往下走,这就是代码「有时可以正常运行」的原因。 - 随机数范围计算错误
你写的映射公式1 + (std::rand() / ((1u + RAND_MAX) / 8))输出范围是1~8,永远生成不了9,哪怕修好死循环bug,也不符合生成1-9范围随机数的初始需求。 - 非致命不良实践
std::srand(std::time(0))是随机数种子初始化语句,整个程序只需要在main函数开头调用一次即可。放在Generate函数内部的话,如果短时间内多次调用Generate,会因为time(0)的精度为秒,拿到相同种子生成完全一致的随机序列。
内容的提问来源于stack exchange,提问作者Ken Za
相关产品推荐
相关产品推荐

