我观察到rand()库函数在循环中只被调用一次时,它几乎总是产生正数。
for (i = 0; i < 100; i++) {
printf("%d\n", rand());
}
但是当我添加两次rand()调用时,生成的数字现在有更多的负数。
for (i = 0; i < 100; i++) {
printf("%d = %d\n", rand(), (rand() + rand()));
}
有人能解释一下为什么我在第二种情况下看到负数吗?
PS:我在循环之前将种子初始化为srand(time(NULL))。
问题是加法。rand()返回int值0…RAND_MAX。所以,如果你把其中的两个加起来,你会得到RAND_MAX * 2。如果它超过了INT_MAX,则加法的结果超出了int可以容纳的有效范围。带符号的值溢出是未定义的行为,可能导致你的键盘用外语与你对话。
由于在这里添加两个随机结果没有任何好处,所以简单的想法就是不要这样做。或者,如果可以保持和,可以在添加之前将每个结果强制转换为unsigned int。或者使用大一点的字体。注意long并不一定比int更宽,如果int至少是64位,这同样适用于long long !
结论:避免加法。它没有提供更多的“随机性”。如果需要更多的位,可以将sum = a + b * (RAND_MAX + 1)的值连接起来,但这也可能需要比int更大的数据类型。
As your stated reason is to avoid a zero-result: That cannot be avoided by adding the results of two rand() calls, as both can be zero. Instead, you can just increment. If RAND_MAX == INT_MAX, this cannot be done in int. However, (unsigned int)rand() + 1 will do very, very likely. Likely (not definitively), because it does require UINT_MAX > INT_MAX, which is true on all implementations I'm aware of (which covers quite some embedded architectures, DSPs and all desktop, mobile and server platforms of the past 30 years).
警告:
尽管在这里已经有一些评论,但请注意,将两个随机值相加并不能得到均匀分布,而是一个三角形分布,就像滚动两个骰子一样:要得到12(两个骰子),两个骰子都必须显示6。对于11,已经有两种可能的变体:6 + 5或5 + 6,等等。
所以,加法从这个方面来说也是不好的。
还要注意rand()生成的结果不是相互独立的,因为它们是由伪随机数生成器生成的。还要注意的是,该标准没有规定计算值的质量或均匀分布。
这是对对这个回答的评论中提出的问题的澄清的回答,
我添加的原因是为了避免在我的代码中使用“0”作为随机数。Rand ()+ Rand()是我脑海中迅速出现的肮脏解决方案。
问题是避免0。提议的解决方案(至少)存在两个问题。一个是,正如其他答案所指出的,rand()+rand()可以调用未定义的行为。最好的建议是永远不要调用未定义的行为。另一个问题是,不能保证rand()不会连续两次产生0。
下面的语句拒绝0,避免未定义的行为,并且在绝大多数情况下将比两次调用rand()更快:
int rnum;
for (rnum = rand(); rnum == 0; rnum = rand()) {}
// or do rnum = rand(); while (rnum == 0);
基本上rand()生成0和RAND_MAX之间的数字,在您的情况下生成2 RAND_MAX > INT_MAX。
可以对数据类型的最大值进行模数处理,以防止溢出。这当然会破坏随机数的分布,但rand只是一种快速获得随机数的方法。
#include <stdio.h>
#include <limits.h>
int main(void)
{
int i=0;
for (i=0; i<100; i++)
printf(" %d : %d \n", rand(), ((rand() % (INT_MAX/2))+(rand() % (INT_MAX/2))));
for (i=0; i<100; i++)
printf(" %d : %ld \n", rand(), ((rand() % (LONG_MAX/2))+(rand() % (LONG_MAX/2))));
return 0;
}