Richard Haris
Richard Haris

Reputation: 21

C++ random number generator without repeating numbers

I have searched high and low for a type of function that turns this code

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

using namespace std;

void ran(int array[], int max);
int main() {
 printf("Today's lottery numbers are:\n");    
 for (int i = 0; i < 6; i++)
  srand((unsigned)(NULL));
}

into a random number generator that ensures no repeating numbers can someone help me with it? after the check I plan to print it with printf("%d\n", rand()%50);

I just need a routine that makes sure its non repeating. Please If you can give me a routine I would be greatly relieved and will be sure to pay it forward.

Thanks. The libraries don't seem to be reading right on this scren but they are stdio, stdlib and time and im using namespace.

Upvotes: 2

Views: 15374

Answers (5)

David
David

Reputation: 3442

And if you have access to C++0x you can use the new random generator facilities that wrap all of this junk for you!

http://www2.research.att.com/~bs/C++0xFAQ.html#std-random

Upvotes: 0

paxdiablo
paxdiablo

Reputation: 881613

You should only call srand once in your code and you should call it with a "random" seed like time(NULL).

By calling srand within the loop, and calling it with a 0 seed each time, you'll get six numbers exactly the same.

However, even with those fixes, rand()%50 may give you the same number twice. What you should be using is a shuffle algorithm like this one since it works exactly the same as the lottery machines.

Here's a complete program showing that in action:

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

static void getSix (int *dst) {
    int sz, pos, i, src[50];
    for (i = 0; i < sizeof(src)/sizeof(*src); i++)
        src[i] = i + 1;
    sz = 50;
    for (i = 0; i < 6; i++) {
        pos = rand() % sz;
        dst[i] = src[pos];
        src[pos] = src[sz-1];
        sz--;
    }
}
int main (void) {
    srand (time (NULL));
    int i, numbers[6];
    getSix (numbers);
    printf ("Numbers are:\n");
    for (i = 0; i < sizeof(numbers)/sizeof(*numbers); i++)
        printf ("   %d\n", numbers[i]);
    return 0;
}

Sample runs:

Numbers are:
   25
   10
   26
   4
   18
   1
Numbers are:
   39
   45
   8
   18
   17
   22
Numbers are:
   8
   6
   49
   21
   40
   28
Numbers are:
   37
   49
   45
   43
   6
   40

Upvotes: 2

Jacob
Jacob

Reputation: 3686

Why not just use what's already in the STL? Looking at your example code, and assuming it's somewhat representative of what you want to do, everything should be in there. (I assume you need a relatively small range of numbers, so memory wouldn't be a constraint)

Using std::random_shuffle, and an std::vector containing the integers in the range you wish your numbers to be in, should give you a sequence of unique random numbers that you need in your example code.

You will still have to call srand once, and once only, before using std::random_shuffle. Not multiple times like you're doing in your current code example.

Upvotes: 3

ssube
ssube

Reputation: 48277

I would recommend using a better random number generation algorithm that can offer that internally, rather than using rand.

The problem with rand() and trying to prevent repeats is that finding an unused number will slow down with every number added to the used list, eventually becoming a very long process of finding and discarding numbers.

If you were to use a more complex pseudo-random number generator (and there are many, many available, check Boost for a few), you'll have an easier time and may be able to avoid the repeats altogether. It depends on the algorithm, so you'll need to check the documentation.

To do it without using any additional libraries, you could prefill a vector or list with sequential (or even random) numbers, making sure each number is present once in the list. Then, to generate a number, generate a random number and select (and remove) that item from the list. By removing each item as it's used, so long as every item was present once to begin with, you'll never run into a duplicate.

Upvotes: 1

xPheRe
xPheRe

Reputation: 2343

If your range of random numbers is finite and small, say you have X different numbers.

  • Create an array with every single number
  • Select a random index I between 0 and X, and get its value
  • Move X value into I position
  • Decrease X and repeat

Upvotes: 2

Related Questions