如何在C语言中以“相同的概率”从0到N-1获取一个随机数?

11 浏览
0 Comments

如何在C语言中以“相同的概率”从0到N-1获取一个随机数?

我知道这可能是一个“老问题”,但我想重点关注概率。

我的第一个问题是:

在C语言中,rand()会给出一个从0RAND_MAX的数字,这个区间中的每个数字被rand()选择的概率相同吗?

第二个问题:

如果rand()让从0RAND_MAX的每个数字具有相同(或近似相同)的选择概率,那么当我想要从0到N-1(N-1 < RAND_MAX)获取一个随机数时,通常会这样做:

rand()%N

但是,如果RAND_MAX不是N的倍数,从0到N-1选择的随机数的概率可能不同。

例如,假设RAND_MAX=150,N=100,当我执行rand()%100时,从0到49的数字被选择的概率会比从50到99的数字更高,因为150不是100的倍数。

在C语言中,是否有一种算法或函数可以让每个随机数被选择的概率相同?

0
0 Comments

问题的出现原因是rand()%N方法得到的随机数在0..N-1范围内的概率分布是不均匀的。解决方法是找到满足M <= RAND_MAXM % N == 0的最大数M,然后在调用rand()时,如果返回的值大于等于M,则重新调用rand(),直到得到一个小于M的值。这样可以保证得到的随机数在0..N-1范围内具有“相同概率”。然而,这个方法并不理想,因为rand()%N方法仍然存在偏差。应该尽可能使用rand()返回的位数来获取随机数。

0
0 Comments

问题的原因:在C语言中,使用rand()函数生成的随机数在0到RAND_MAX之间,但是这些随机数并不是完全均匀分布的,可能存在一定的偏差。

解决方法:为了获得0到N-1之间的随机数,可以使用如下的方法:

1. 首先,判断N是否小于等于RAND_MAX,如果不满足,需要使用其他的解决方案。

2. 计算rmax的值,公式为:rmax = RAND_MAX - (RAND_MAX % N) - 1。这个值表示了在生成随机数时需要舍弃的范围。

3. 使用一个循环,每次调用rand()函数生成一个随机数,并判断这个随机数是否大于rmax,如果大于,则需要重新生成随机数,直到生成的随机数小于等于rmax为止。

4. 最后,将生成的随机数模上N,即可得到一个均匀分布在0到N-1之间的随机数。

示例:假设RAND_MAX为32767,N为100,那么rmax的值将为32699。在32700到32767的范围内生成的随机数将会被舍弃,需要重新生成随机数,这样可以消除%N操作带来的偏差。

需要注意的是,这种方法并不能解决rand()函数本身的不足之处。C语言并没有规定rand()函数的质量,只要求它生成的值在0到RAND_MAX之间,而RAND_MAX至少为32767。对于大于RAND_MAX的N值,需要使用其他的解决方案。

0
0 Comments

问题的原因是rand()函数生成的随机数并不是真正的随机数,而是依赖于系统提供的随机数生成方式,因此无法确定结果的真正随机性。如果需要非常重要的随机性,最好使用涉及硬件的解决方案。另外,在使用模运算时,会导致结果偏向某些数值,从而引入偏差。解决这个问题的方法是将随机数转换为浮点数,通过除以随机生成器能提供的最大值,然后乘以你希望处理的数值范围的个数。如果你的范围不是从0开始的,还需要加上你期望的基准值。C语言的规范没有规定特定的实现方式,但是对rand/srand函数的约束几乎可以保证它是一个线性同余生成器(LCG)。但最重要的是,通过浮点数回到整数仍然会给出有偏差的结果,尽管不那么明显。

0