在不连续范围内生成随机数的最佳方法是什么?

Nae*_*Nae 3 c algorithm

有没有比以下更好的方式:

#define BOUND 7

int r;
int e = 1;

r = rand() % BOUND;

while (r == e){

    r = rand() % BOUND;
}
Run Code Online (Sandbox Code Playgroud)

用于生成除值之外的范围内的数字e

Azi*_*ziz 10

您要求的是在[0, BOUND)不包括该值的范围内生成随机数e

这里解释算法似乎是不使用循环的最佳方法.

这是C代码:

#define BOUND 7

int r;
int e = 1;

r = rand() % (BOUND-1);

if (r >= e){
    r = r+1;
}
Run Code Online (Sandbox Code Playgroud)

因此,您基本上生成范围中的值[0, BOUND-1),如果该值大于或等于排除值e,则将随机数递增1.

请记住,使用randwith %并不能保证生成的数字之间有严格的均匀分布.有关详细信息,请查看此问题/答案.


chq*_*lie 5

要在值之间具有均匀分布的范围内生成伪随机数,使用返回值的大小rand()而不是其余部分来进行除法更加可靠rand() % BOUND:

int r = (long long)rand() * BOUND / (RAND_MAX + 1LL);
Run Code Online (Sandbox Code Playgroud)

rand()返回一个介于0RAND_MAX包含的值:除法必须使用,RAND_MAX + 1LL因此结果0包含在范围内.. BOUND排除(由chux评论).

如果要排除给定值,请将范围减小1并调整结果:

#define BOUND 7

int r = (long long)rand() * (BOUND - 1) / (RAND_MAX + 1LL);
if (r >= 1) { // shift values 1..5 to 2..6
    r += 1;
}
Run Code Online (Sandbox Code Playgroud)

这是一个更通用的版本:

// select a random value from a set
int set[] = { 0, 2, 3, 4, 5, 6 };
int r = set[(long long)rand() * (sizeof(set) / sizeof(*set)) / (RAND_MAX + 1LL)];
Run Code Online (Sandbox Code Playgroud)