c – 均匀分布的随机数生成

为什么这段代码会生成均匀分布的数字?我理解它有些困难.有人能解释一下吗谢谢.

int RandomUniform(int n) {  
  int top = ((((RAND_MAX - n) + 1) / n) * n - 1) + n;  
  int r;  
  do {  
    r = rand();  
  } while (r > top);  
  return (r % n);  
}

更新:我明白为什么rand()%n不会给你一个均匀分布的序列.我的问题是为什么

top = ((((RAND_MAX - n) + 1) / n) * n - 1) + n;

这里有什么问题?我认为一个简单的顶部= RAND_MAX / n * n就行了.

最佳答案
该函数假定rand()是均匀分布的;这是否是一个有效的假设取决于rand()的实现.

给定一个统一的rand(),我们可以通过计算rand()%n得到[0,n]范围内的随机数.但是,一般来说,这不会很均匀.例如,假设n为3且RAND_MAX为7:

rand()      0 1 2 3 4 5 6 7
rand() % n  0 1 2 0 1 2 0 1

我们可以看到0和1的概率为3/8,而2只出现2/8的概率:分布不均匀.

您的代码会丢弃任何大于或等于它可以生成的n的最大倍数的rand()值.现在每个值的概率相等:

rand()      0 1 2 3 4 5 6 7
rand() % n  0 1 2 0 1 2 X X

所以0,1和2都有1/3的概率,只要我们不那么不幸,循环永远不会终止.

关于你的更新:

I think a simple top = RAND_MAX / n * n would do.

如果RAND_MAX是一个独占边界(比实际最大值多一个),那么这是正确的.由于它是一个包容性的界限,我们需要添加一个来获得独占界限;并且由于以下逻辑与>进行比较对于包含边界,然后在计算后再次减去一个:

int top = ((RAND_MAX + 1) / n) * n - 1;

但是,如果RAND_MAX等于INT_MAX,则计算将溢出;为避免这种情况,在计算开始时减去n,并在结尾处再次添加:

int top = (((RAND_MAX - n) + 1) / n) * n - 1 + n;

转载注明原文:c – 均匀分布的随机数生成 - 代码日志