在C中生成“范围内”随机数

时间:2012-07-03 17:39:44

标签: c

我需要生成[0,10]范围内的随机数,以便:

  • 所有数字都出现一次。
  • 没有重复的结果。

有人可以指导我使用哪种算法吗?

3 个答案:

答案 0 :(得分:11)

Richard J. Ross的答案中的算法不正确。它会生成n^n个可能的排序,而不是n!。 Jeff Atwood博客上的这篇文章说明了这个问题:http://www.codinghorror.com/blog/2007/12/the-danger-of-naivete.html

相反,你应该使用Knuth-Fisher-Yates Shuffle:

int values[11] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
srand(time(NULL));

for (int i = 10; i > 0; i--)
{
    int n = rand() % (i + 1);

    int temp = values[n];
    values[n] = values[i];
    values[i] = temp;
}

答案 1 :(得分:1)

尝试使用伪随机数的算法:

int values[11] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
srand(time(NULL));

for (int i = 0; i < 11; i++)
{
    int swap1idx = rand() % 11;
    int swap2idx = rand() % 11;

    int tmp = values[swap1idx];
    values[swap1idx] = values[swap2idx];
    values[swap2idx] = tmp;
}

// now you can iterate through the shuffled values array.

请注意,这取决于模数偏差,但它应该适用于您需要的内容。

答案 2 :(得分:0)

尝试创建一个随机函数,如下所示:

void randomize(int v[], int size, int r_max) {
    int i,j,flag;

    v[0] = 0 + rand() % r_max; // start + rand() % end
    /* the following cycle manages, discarding it,
the case in which a number who has previously been extracted, is re-extracted. */
    for(i = 1; i < size; i++) {
        do {
            v[i]= 0 + rand() % r_max;
            for(j=0; j<i; j++) {
                if(v[j] == v[i]) {
                    flag=1;
                    break;
                }
                flag=0;
            }
        } while(flag == 1);
    }
}

然后,只需调用它传递11个元素的数组v[],其大小和上限:

randomize(v, 11, 11);

该数组由于它是作为参数通过引用传递的事实,将被随机化,没有重复,并且数字出现一次。

请在致电srand(time(0));之前致电randomize,并初始化int v[11]={0,1,2,3,4,5,6,7,8,9,10};