Bash循环调用C程序结果异常问题求助
你遇到的这个问题其实是个很典型的「快速循环启动程序导致随机种子重复」的坑,我来给你拆解一下:
首先,你的C程序里应该是用了rand()生成随机数,但初始化种子的方式大概率依赖秒级时间戳(比如time(NULL))。单独运行时,每次启动程序的间隔至少有几秒,time(NULL)返回的数值不一样,所以种子不同,生成的随机数序列也不同,二叉树深度自然有差异。但Bash循环跑500次的速度非常快,可能所有程序实例都在同一秒钟内启动,这时候time(NULL)返回的是同一个秒数,导致每次程序初始化的随机种子完全相同——那生成的随机数序列肯定一模一样,二叉树的结构也就没区别,深度结果自然重复了。
下面给你几个可行的解决方案,按推荐程度排序:
方案1:改用微秒级时间戳初始化种子(C程序内部修改)
把原来用time(NULL)的地方换成更精细的时间单位,比如用gettimeofday()获取微秒数,这样哪怕同一秒内启动多次程序,种子也会不一样。示例代码如下:
#include <sys/time.h> #include <stdlib.h> // 在程序开头初始化随机种子 int main() { struct timeval tv; gettimeofday(&tv, NULL); unsigned int seed = tv.tv_sec * 1000000 + tv.tv_usec; srand(seed); // 你的原有业务逻辑... return 0; }
这样修改后,不管Bash循环跑多快,每次程序启动的微秒数都不同,种子就不会重复了。
方案2:通过命令行参数传入随机种子(结合Bash循环)
如果不想修改C程序,也可以让程序接受一个命令行参数作为种子,然后在Bash循环里每次传入不同的值。
首先修改C程序,支持读取命令行参数:
#include <stdio.h> #include <stdlib.h> #include <time.h> int main(int argc, char *argv[]) { // 如果有传入参数,就用参数作为种子;否则用默认的秒级时间戳 if (argc > 1) { unsigned int seed = atoi(argv[1]); srand(seed); } else { srand(time(NULL)); } // 你的原有业务逻辑... return 0; }
然后修改Bash循环,比如用循环的索引值作为种子:
for i in {1..500}; do ./myProgram $i >> result.txt done
或者用Bash内置的$RANDOM变量(每次调用都会生成0-32767的随机数):
for i in {1..500}; do ./myProgram $RANDOM >> result.txt done
方案3:在Bash循环中加入微小延迟(不推荐)
这个方法比较取巧,就是在每次循环之间加一个很短的延迟,确保每次程序启动都在不同的秒数里:
for i in {1..500}; do ./myProgram >> result.txt sleep 0.1 # 延迟0.1秒 done
但这个方法会让整个循环的运行时间变长(500次就是50秒),而且如果系统负载高,可能还是会有重复的情况,所以不如前两个方案可靠。
最后再提醒一下:如果你原来的C程序根本没调用srand()初始化种子,那默认种子是1,不管怎么运行,生成的随机数序列都是固定的——不过你说单次运行结果不同,应该不是这种情况,但还是可以检查一下程序里有没有srand()的调用。
内容的提问来源于stack exchange,提问作者Dongho Han

