在C中生成唯一的随机数

时间:2011-02-21 09:44:42

标签: c

我尝试在C中生成10个唯一的随机数。我有10个数字的数组numout[]但是在一段时间后会出现“分段错误”。

代码是:

int i,j,numout[10],randnum;

void main()
{
    srand(time(NULL));  
    for(i=0;i<10;i++)
    {
        numout[i]=generate();
        printf("%d",numout[i]);
        fflush(stdout);
        sleep(1);
        printf("\b");
    }
}
int generate()
{
    randnum=1+(int)(rand()*mul_val/(RAND_MAX+1.0));
    for(j=0;j<i;j++)
    {
        if(randnum==0 || randnum==numout[j])
        {
            randnum=generate();     
        }
    }
    return(randnum);
}

4 个答案:

答案 0 :(得分:12)

认真地抛弃那些代码。您需要一个shuffling算法,而不是一段代码来检查重复项的旧值。随着游泳池的耗尽,按照自己的方式进行游戏将会花费更长的时间。混洗算法的优点是随着池变小而不会降低。

这是我在回答不同问题时使用的一段代码。它维护一个数字列表,当它返回一个随机数字时,它会从列表中删除它并减少下一个随机选择的计数。

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

#define ERR_NO_NUM -1
#define ERR_NO_MEM -2

int myRandom (int size) {
    int i, n;
    static int numNums = 0;
    static int *numArr = NULL;

    // Initialize with a specific size.

    if (size >= 0) {
        if (numArr != NULL)
            free (numArr);
        if ((numArr = malloc (sizeof(int) * size)) == NULL)
            return ERR_NO_MEM;
        for (i = 0; i  < size; i++)
            numArr[i] = i;
        numNums = size;
    }

    // Error if no numbers left in pool.

    if (numNums == 0)
       return ERR_NO_NUM;

    // Get random number from pool and remove it (rnd in this
    //   case returns a number between 0 and numNums-1 inclusive).

    n = rand() % numNums;
    i = numArr[n];
    numArr[n] = numArr[numNums-1];
    numNums--;
    if (numNums == 0) {
        free (numArr);
        numArr = 0;
    }

    return i;
}

int main (void) {
    int i;

    srand (time (NULL));
    i = myRandom (20);
    while (i >= 0) {
        printf ("Number = %3d\n", i);
        i = myRandom (-1);
    }
    printf ("Final  = %3d\n", i);
    return 0;
}

示例输出显示了它的实际效果:

Number =  19
Number =  10
Number =   2
Number =  15
Number =   0
Number =   6
Number =   1
Number =   3
Number =  17
Number =  14
Number =  12
Number =  18
Number =   4
Number =   9
Number =   7
Number =   8
Number =  16
Number =   5
Number =  11
Number =  13
Final  =  -1

使用非负池大小调用它,它会设置一个新序列并返回第一个随机值。接下来,您可以使用-1调用它,它将从池中获取下一个随机的唯一编号。当池耗尽时,它将返回-1。

如果您希望能够在线程代码中使用此函数,则包含此代码的other answer具有可以维护多个池的版本。

答案 1 :(得分:3)

当您的堆栈空间不足时,您将收到分段错误。您的代码是递归的(即generate()调用generate())。因此,当您用完未使用的随机数时,它将永远自行调用。

但是,我不会建议您修复代码,因为您确实需要从头开始重新编写代码。请关注paxdiablo的例子。

答案 2 :(得分:1)

如果您需要大量独特的随机数,则应考虑使用LFSR方法。 LFSR生成不会重复的唯一随机数,除非整个池耗尽,因此32位LFSR将生成2 ^ 32 - 1个唯一随机数 - 它不会生成0.编码是直接的,查找它谷歌。

答案 3 :(得分:-1)

The program below stores n unique random numbers i.e, from [1 to n] in an array.

#include<iostream.h>
#include<conio.h>

void main()
{

int i, j, Array[100];
cout<<"Enter value of n : ";     //upper limit
cin>>n;

randomize();

int rnd;

Array[1]=rand()%n+1;

for(i=2;i<=n;i++)
{
    rnd=rand()%n+1;

     for(j=1;j<i;j++)
     {
        if(rnd==Array[j])
        {
            i--;
            break;
        }
    }

        if(j>=i)
        Array[i]=rnd;
}



//for printing from random numbers from 1 to n
for(i=1;i<=n;i++)
cout<<Array[i]<<"\n";

getch();
}