C Programming – Generating Unique Random Numbers

c++

I tried generating 10 unique random numbers in C. I have an array numout[] for 10 numbers but this gets to "segmentation fault" after some time.

Tho code is:

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);
}

Best Answer

Throw that code away, seriously. You need a shuffling algorithm, not a piece of code that checks older values for duplicates. Doing it your way will end up taking longer and longer as your pool runs out. The advantage of a shuffling algorithm is that it doesn't degrade as the pool becomes smaller.

Here's a piece of code I used in answering a different question. It maintains a list of numbers and, when it returns a random one to you, it removes it from the list and decrements the count for the next random selection.

#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;
}

A sample output shows it in action:

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

Call it with a non-negative pool size and it sets up a new sequence and returns the first random value. Following that, you can call it with -1 and it will get the next random, unique number from the pool. When the pool is exhausted, it will return -1.

The other answer that contained this code has a version that can maintain multiple pools as well if you want to be able to use this function in threaded code.

Related Question