为什么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()定义为返回0RAND_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 + 55 + 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

上一篇: Why does rand() + rand() produce negative numbers?

下一篇: Applicative instance for MaybeT m assumes Monad m