简单做法

C语言有个rand()函数，会返回一随机数值，范围在0至RAND_MAX间。于是很容易想到一个简单的做法

// Return a random number in [0,RANGE)
x = rand () % RANGE;


1. rand()等概率返回[0, RAND_MAX]间这RAND_MAX+1个数中的任意一个，如果RAND_MAX+1不能被RANGE整除，那么这个[0, RANGE)分布就blatantly不均匀了。举个例子RAND_MAX=32767，目标区间为[0,10)，32767%10=7,则(7,10)间数的取值概率小于[0,7]间数。

2. rand()的伪随机性。大多数随机数发生器产生随机数的低位bits都distressingly不随机（有一个short cyclical pattern或者bits间有依赖关系）。

3. RAND_MAX在<stdlib.h>中定义,其值最小为32767(215-1),最大为2147483647(231-1),假如RAND_MAX+1 < RANGE呢？

RANGE<=RAND_MAX+1

方法1

(int)(rand() / (RAND_MAX + 1.0) * RANGE)


方法2

int myrandom_range(int start,int end) {//[start,end)
int N = end - start;
int bound = (RAND_MAX + 1) / N * N;
int r;
do {
r = rand();
} while (r >= bound);
return start + int(r / (RAND_MAX + 1.0) * N);
}


Let p = (RAND_MAX % RANGE) / (RAND_MAX + 1.0). This is the probability that any given call to rand() will require a retry. Note that this value is maximized when RANGE*2 = RAND_MAX+3, and which will yield a value of p roughly equal to 1/2.

• The average number of times that rand() will be called is 1/(1-p) (with a worst case of about 2).
• The probability that at least n calls to rand() will be required beyond the first one is pn.
So for most values of p which will be much less than 1/32 say, performance should not be a concern at all.

RANGE>RAND_MAX+1

方法2++

int Rand7(){
int x;
do {
x = 5 * (Rand5() - 1) + Rand5() // Rand25
} while(x > 21)
return x%7 + 1;
}


方法1++

inline unsigned __int32 rand32(){
return ((rand()&0x00007FE0)>>5) + ((rand()&0x00007FF0)<<6) + ((rand()&0x00007FF0)<<17);
}


题外话

随机洗牌 (CC150v5-18.2)

1/(i+1) * (i+1)/(i+2) * (i+2)/(i+3) ... (N-2)/(N-1) * (N-1)/N = 1/N

长度为N(未知)的序列中随机取出k个元素 (编程珠玑12.3)

(k/ (i+1)) * (1 - 1/(i+2)) * (1 - 1/(i+3)...(1 - 1/(N+1))) = k/(N+1)

参考

C++生成随机数——生成任意范围内的等概率随机数