c – 我应该使用“rand%N”还是“rand()/(RAND_MAX / N 1)”?

前端之家收集整理的这篇文章主要介绍了c – 我应该使用“rand%N”还是“rand()/(RAND_MAX / N 1)”?前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。
我正在阅读 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

两种选择对我来说都是完全随机的.甚至看起来第二种方法比兰特%N更差.

我应该使用rand()%N还是rand()/(RAND_MAX / N 1)?

解决方法

如果N是2的幂,则使用余数技术通常是安全的(RAND_MAX通常是2的幂-1,因此整个范围具有两个长度的幂).更一般地,N必须除以rand()的范围以避免偏差.

否则,无论rand()的质量如何,都会遇到this problem.简而言之,问题在于你将该范围切割成长度为N的多个“部分”,如果N不分割范围则最后部分将不完整.因此,从该部分“切断”的数字不太可能发生,因为它们可以从中生成更少的“部分”.

不幸的是rand()/(RAND_MAX / N 1)也被破坏了(几乎以同样的方式),所以真正的答案是:不要使用它们中的任何一个.

上面提到的问题非常重要,除非Y除以X,否则无法在Y结果上均匀分布X个不同的值.您可以通过拒绝一部分随机样本来修复它,使Y除以新的X.

猜你在找的C&C++相关文章