gpt4 book ai didi

c - "n * (rand()/RAND_MAX)"是否产生偏斜的随机数分布?

转载 作者:太空狗 更新时间:2023-10-29 16:47:10 28 4
gpt4 key购买 nike

我想找到一种在 C 中获取随机数的不偏斜的方法(尽管我最多将它用于 0-20 的值,更可能只有 0-8)。我看过这个公式,但在运行了一些测试后,我不确定它是否有偏差。有帮助吗?

这里是使用的完整函数:

int randNum() 
{
return 1 + (int) (10.0 * (rand() / (RAND_MAX + 1.0)));
}

我使用:

unsigned int iseed = (unsigned int)time(NULL);
srand (iseed);

下面建议的那个拒绝为我工作我试过了

int greek; 
for (j=0; j<50000; j++)
{
greek =rand_lim(5);
printf("%d, " greek);
greek =(int) (NUM * (rand() / (RAND_MAX + 1.0)));
int togo=number[greek];
number[greek]=togo+1;
}

当我注释掉 printf 时,它停止工作并给了我相同的数字 50000 次。

最佳答案

是的,它是有偏差的,除非你的 RAND_MAX 恰好是 10 的倍数。

如果你把从 0 到 RAND_MAX 的数字,试着把它们分成 10 堆,你真的只有三种可能性:

  1. RAND_MAX 是 10 的倍数,堆成偶数。
  2. RAND_MAX 不是 10 的倍数,堆出来的东西不均匀。
  3. 开始时将其分成不均匀的组,但丢弃所有会使它不均匀的“额外”。

您很少能控制 RAND_MAX,而且它通常是一个素数。这实际上只剩下 2 和 3 作为可能性。

第三个选项大致如下所示:[编辑:经过一番思考,我修改了它以生成 0...(limit-1) 范围内的数字,以适应 C 和 C++ 中大多数事物的工作方式。这也简化了代码(一点点)。

int rand_lim(int limit) {
/* return a random number in the range [0..limit)
*/

int divisor = RAND_MAX/limit;
int retval;

do {
retval = rand() / divisor;
} while (retval == limit);

return retval;
}

对于任何质疑此方法是否会留下一些偏差的人,我还编写了一个完全不同的版本,纯粹用于测试。这一个使用范围非常有限的绝对非随机生成器,因此我们可以简单地遍历范围内的每个数字。它看起来像这样:

#include <stdlib.h>
#include <stdio.h>

#define MAX 1009

int next_val() {
// just return consecutive numbers
static int v=0;

return v++;
}

int lim(int limit) {
int divisor = MAX/limit;
int retval;

do {
retval = next_val() / divisor;
} while (retval == limit);

return retval;
}

#define LIMIT 10

int main() {

// we'll allocate extra space at the end of the array:
int buckets[LIMIT+2] = {0};
int i;

for (i=0; i<MAX; i++)
++buckets[lim(LIMIT)];

// and print one beyond what *should* be generated
for (i=0; i<LIMIT+1; i++)
printf("%2d: %d\n", i, buckets[i]);
}

因此,我们从 0 到 1009 之间的数字开始(1009 是质数,因此它不会是我们选择的任何范围的精确倍数)。所以,我们从 1009 个数字开始,并将其分成 10 个桶。这应该在每个桶中提供 100 个,并且 9 个剩菜(可以这么说)被 do/while 循环“吃掉”。正如现在所写的那样,它分配并打印出一个额外的桶。当我运行它时,我在每个桶 0..9 中得到恰好 100,在桶 10 中得到 0。如果我注释掉 do/while 循环,我明白了0..9 各有 100 个,桶 10 有 9 个。

可以肯定的是,我已经针对生成的范围(主要使用素数)和桶数使用各种其他数字重新运行测试。到目前为止,我无法让它在任何范围内产生偏斜的结果(当然,只要 do/while 循环被启用)。

另一个细节:我在此算法中使用除法而不是余数是有原因的。对于 rand() 的良好(甚至体面)实现,它是无关紧要的,但是当您使用除法将数字限制在一个范围内时,您保持上限 输入的位。当你用余数做它时,你保留了输入的位。碰巧的是,对于典型的线性同余伪随机数生成器,低位往往不如高位随机。一个合理的实现会丢弃一些最低有效位,从而使它变得无关紧要。另一方面,rand 有一些非常糟糕的实现,并且对于其中的大多数,您最终通过使用除法而不是余数来获得更好的输出质量。

我还应该指出,生成器的作用大致相反——低位比高位更随机。至少以我的经验,这些是非常罕见的。高位更随机的相当更常见。

关于c - "n * (rand()/RAND_MAX)"是否产生偏斜的随机数分布?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/10219355/

28 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com