【发布时间】:2015-02-26 16:32:08
【问题描述】:
我正在阅读C FAQ 并在question 中发现它建议我使用rand() / (RAND_MAX / N + 1) 而不是更流行的方式rand() % N。
原因是当N 是一个小数字时,rand() % N 将只使用来自rand() 的几个位。
我在 Windows 和 Linux 上测试了 N 为 2 的不同方法,但没有发现差异。
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#define N 2
int main(void)
{
srand(0);
printf("rand() %% N:\n");
for (int i = 0; i < 40; ++i) {
printf("%d ", rand() % N);
}
putchar('\n');
srand(0);
printf("rand() / (RAND_MAX / N + 1):\n");
for (int i = 0; i < 40; ++i) {
printf("%d ", rand() / (RAND_MAX / N + 1));
}
putchar('\n');
return 0;
}
输出是这样的(在我的 gnu/linux 机器上):
rand() % N:
1 0 1 1 1 1 0 0 1 1 0 1 0 1 1 0 0 0 0 0 1 0 1 1 0 0 0 1 1 1 1 0 0 0 1 1 1 0 1 0
rand() / (RAND_MAX / N + 1):
1 0 1 1 1 0 0 1 0 1 0 1 0 1 1 1 1 1 0 1 0 0 0 1 0 0 0 0 1 0 1 1 1 0 1 1 0 1 0 1
在我看来,这两种选择都是完全随机的。甚至看起来第二种方法比rand % N更糟糕。
我应该使用rand() % N 还是rand() / (RAND_MAX / N + 1)?
【问题讨论】:
-
这不是您在这种情况下注意到差异的方式。你的错误是这样的:“这两种选择对我来说都是完全随机的”。您需要一种分析方法。可以这样想:真正衡量这一点的唯一方法是获取无限长序列的一些统计数据。
-
这是
#define N 2的一个糟糕示例,因为RAND_MAX是一个奇数,而rand() % N将返回0 和1 的相等分布,因为伪随机生成器的限制。这里的两种方法绝对没有区别,只是在伪随机结果的顺序上。但是(通常)N越大,模偏差越显着。
标签: c algorithm random numbers