为什么rand()+ rand()产生负数?
我观察到rand()
库函数在循环中只调用一次,它几乎总是产生正数。
for (i = 0; i < 100; i++) {
printf("%dn", rand());
}
但是,当我添加两个rand()
调用时,生成的数字现在有更多的负数。
for (i = 0; i < 100; i++) {
printf("%d = %dn", rand(), (rand() + rand()));
}
有人能解释为什么我在第二种情况下看到负数?
PS:我将循环之前的种子初始化为srand(time(NULL))
。
rand()
定义为返回0
到RAND_MAX
之间的整数。
rand() + rand()
可能会溢出。 你观察到的可能是由整数溢出引起的未定义行为的结果。
问题是增加。 rand()
返回一个int
值为0...RAND_MAX
。 所以,如果你添加其中两个,你将达到RAND_MAX * 2
。 如果超出INT_MAX
,则加法结果会溢出int
可以保持的有效范围。 有符号值的溢出是未定义的行为,并可能导致您的键盘以外语方式与您通话。
由于在这里添加两个随机结果没有任何好处,所以简单的想法就是不去做。 或者,如果可以保存总和,则可以在添加之前将每个结果转换为unsigned int
。 或者使用更大的类型。 需要注意的是long
不一定比更宽int
,同样也适用于long long
,如果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()
生成的结果并不相互独立,因为它们是由伪随机数生成器生成的。 还要注意,该标准没有规定计算值的质量或均匀分布。
这是澄清在回答这个问题时发表的问题的答案,
我添加的原因是为了避免在我的代码中使用“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);
链接地址: http://www.djcxy.com/p/68035.html