我观察到rand()库函数在循环中只调用一次,它几乎总是产生正数.
for (i = 0; i < 100; i++) {
printf("%d\n", rand());
}
Run Code Online (Sandbox Code Playgroud)
但是当我添加两个rand()电话时,现在生成的数字会有更多的负数.
for (i = 0; i < 100; i++) {
printf("%d = %d\n", rand(), (rand() + rand()));
}
Run Code Online (Sandbox Code Playgroud)
有人可以解释为什么我在第二种情况下看到负数吗?
PS:我在循环之前初始化种子为srand(time(NULL)).
P.P*_*.P. 541
rand()被定义为在0和之间返回一个整数RAND_MAX.
rand() + rand()
Run Code Online (Sandbox Code Playgroud)
可能会溢出 您观察到的可能是整数溢出导致的未定义行为的结果.
too*_*ite 88
问题是增加.rand()返回int值0...RAND_MAX.所以,如果你添加其中两个,你就可以了RAND_MAX * 2.如果超过INT_MAX,则添加的结果溢出int可以容纳的有效范围.签名值溢出是未定义的行为,可能导致您的键盘用外语说话.
由于添加两个随机结果没有增益,简单的想法就是不这样做.或者,unsigned int如果可以保存总和,则可以在添加之前将每个结果转换为.或者使用更大的类型.注意,long不一定要宽int,同样适用于long longif int至少是64位!
结论:避免添加.它没有提供更多的"随机性".如果需要更多位,可以连接值sum = a + b * (RAND_MAX + 1),但这也可能需要更大的数据类型int.
正如你所陈述的原因是为了避免零结果:通过添加两个rand()调用的结果无法避免,因为两者都可以为零.相反,你可以增加.如果RAND_MAX == INT_MAX,这不能做到int.但是,(unsigned int)rand() + 1非常非常可能.可能(不是最终),因为它确实需要UINT_MAX > INT_MAX,这在我所知道的所有实现中都是如此(其中涵盖了过去30年中的一些嵌入式架构,DSP和所有桌面,移动和服务器平台).
警告:
虽然这里已经有评论,但请注意,添加两个随机值并不能得到均匀分布,而是像滚动两个骰子一样的三角形分布:得到12(两个骰子)两个骰子都必须显示6.因为11已经有两种可能的变体:6 + 5或者5 + 6等等
因此,从这方面来说,增加也是不好的.
还要注意,rand()生成的结果不是彼此独立的,因为它们是由伪随机数生成器生成的.另请注意,标准未指定计算值的质量或均匀分布.
Dav*_*men 36
我添加的原因是为了避免'0'作为我的代码中的随机数.rand()+ rand()是我想到的快速肮脏的解决方案.
问题是避免0.建议的解决方案存在(至少)两个问题.一个是,正如其他答案所示,rand()+rand()可以调用未定义的行为.最好的建议是永远不要调用未定义的行为.另一个问题是不能保证rand()不会连续两次产生0.
以下拒绝零,避免未定义的行为,并且在绝大多数情况下将比两次调用更快rand():
int rnum;
for (rnum = rand(); rnum == 0; rnum = rand()) {}
// or do rnum = rand(); while (rnum == 0);
Run Code Online (Sandbox Code Playgroud)