Non-repeating random number generator

2020-04-07 05:51发布

问题:

I'd like to make a number generator that does not repeat the number it has given out already (C++).

All I know is:

int randomgenerator(){
  int random;
  srand(time(0));
  random = rand()%11;
  return(random);
} // Added this on edition

That function gives me redundant numbers.

I'm trying to create a questionnaire program that gives out 10 questions in a random order and I don't want any of the questions to reappear.

Does anyone know the syntax?

回答1:

What I would do:

  • Generate a vector of length N and fill it with values 1,2,...N.
  • Use std::random_shuffle.
  • If you have say 30 elements and only want 10, use the first 10 out the vector.

EDIT: I have no idea how the questions are being stored, so.. :)

I am assuming the questions are being stored in a vector or somesuch with random access. Now I have generated 10 random numbers which don't repeat: 7, 4, 12, 17, 1, 13, 9, 2, 3, 10.

I would use those as indices for the vector of questions:

std::vector<std::string> questions;
//fill with questions
for(int i = 0; i < number_of_questions; i++)
{
    send_question_and_get_answer(questions[i]);
}


回答2:

You are trying to solve the problem "the wrong way".

Try this instead (supposing you have a vector<int> with question ids, but the same idea will work with whatever you have):

  1. Get a random R from 0 to N-1 where N is the number of questions in the container
  2. Add question R to another collection of "selected" questions
  3. If the "selected questions" collection has enough items, you 're done
  4. Remove question R from your original container (now N has decreased by 1)
  5. Go to 1


回答3:

Sounds like you essentially want to shuffle a deck of cards (in this case, the "cards" being the questions, or question numbers).

In C++, I would do:

#include <vector>
#include <algorithms>

std::vector<int> question_numbers;
for (unsigned int i = 0; i < 10; ++i)
    question_numbers.push_back(i+1);
std::random_shuffle(question_numbers.begin(), question_numbers.end());

// now dole out the questions based on the shuffled numbers

You do not have to hand out all of the questions, any more than you have to deal out a whole deck of cards every time you play a game. You can, of course, but there's no such requirement.



回答4:

Create a vector of 10 elements (numbers 1-10), then shuffle it, with std::random_shuffle. Then just iterate through it.



回答5:

Should look more like this: (Note: does not solve your original problem).

int randomgenerator(){
  int random;

  // I know this looks re-dunand compared to %11
  // But the bottom bits of rand() are less random than the top
  // bits do you get a better distribution like this.

  random = rand() / (RAND_MAX / 11);

  return random;
}

int main()
{
    // srand() goes here.
    srand(time(0));

    while(true)
    {
        std::cout << randomgenerator() << "\n";
    }
}

A better way to solve the original problem is to pre-generate the numbers so you know that each number will appear only once. Then shuffle the order randomly.

int main()
{
    int data[] =  { 0,1,2,3,4,5,6,7,8,9,10,11};
    int size   =  sizeof(data)/sizeof(data[0]);

    std::random_shuffle(data, data + size);

    for(int loop = 0; loop < size; ++loop)
    {
        std::cout << data[loop] << "\n";
    }
}


回答6:

//non repeating random number generator
for (int derepeater = 0; derepeater < arraySize; derepeater++)
{
    for (int j = 0; j < arraySize; j++)
    {
        for (int i = arraySize; i > 0; i--)
        {
            if (Compare[j] == Compare[i] && j != i)
            {
                Compare[j] = rand() % upperlimit + 1;
            }
        }
    }
}


回答7:

Why not use some STL to perform the checks for you? The idea:

Create an (initially empty) set of 10 integers that will be the indices of the random questions (they will be distinct as a set forbids duplicate items). Keep pushing random numbers in [0, num_of_questions-1] in there until it grows to a size of 10 (duplicates will get rejected automatically). When you have that set ready, iterate over it and output the questions of the corresponding indexes:

std::vector<std::string> questions = /* I am assuming questions are stored in here */
std::set<int> random_indexes;

/* loop here until you get 10 distinct integers */
while (random_indexes.size() < 10) random_indexes.insert(rand() % questions.size());

for (auto index: random_indexes){
    std::cout << questions[index] <<std::endl;
}

I may be missing something, but it seems to me the answers that use shuffling of either questions or indexes perform more computations or use an unnecessary memory overhead.