如何生成7个随机数,而不重复

时间:2019-05-14 18:38:33

标签: c++ arrays random

我想从0到39生成7个随机数,并将它们存储在一维数组中。我必须确保每个数字都不同(例如不能有两个7)。

我考虑过改组数字,但是我只需要40个中的7个。实际上我必须在学校做这个,我们还没有涉及到指针,我们正在使用rand()函数来获取随机数。我猜想解决方案并不一定要是真正随机的,至少要有一定的可能性。

4 个答案:

答案 0 :(得分:3)

好的,这是我的贡献:

#include <iostream>
#include <algorithm>
#include <random>
#include <vector>

int main()
{
    std::vector <int> v (40);
    std::generate (v.begin (), v.end (), [n = 0] () mutable { return n++; });

    std::random_device rd;
    std::mt19937 g (rd ());
    std::shuffle (v.begin (), v.end (), g);

    for (int i = 0; i < 7; ++i)
        std::cout << v [i] << '\n';
}

代表输出:

5
39
10
17
36
11
31

Live demo

编辑:如skeller所述,对std::generate的呼叫可以替换为:

std::iota (v.begin (), v.end (), 0);

整洁很多。

如果愿意,也可以将std::vector v (40);替换为std::array <int, 40> v;

答案 1 :(得分:0)

有人在评论中指出,教导现代随机方法很重要。所以这是我的看法:

现代C ++方法

#include <iostream>
#include <algorithm>
#include <vector>
#include <numeric>
#include <random>
using namespace std;

int main()
{
  std::vector<int> AllValues(40) ; // Vector of 40 integers
  std::iota (std::begin(AllValues), std::end(AllValues), 0); // Fill AllValues with 0..39
  std::random_device RandomDevice; // Create a random device
  std::default_random_engine RandomEngine(RandomDevice()); // Create a random engine, seeding from RandomDevice  
  std::shuffle(std::begin(AllValues), std::end(AllValues), RandomEngine);  // Shuffle AllValues using RandomEngine
  std::vector<int> RandomNumbers(AllValues.begin(), AllValues.begin() + 7); // Create a new vector using the first 7 numbers of AllValues

  // Display the 7 random values
  for (auto i: RandomNumbers)
    std::cout << i << std::endl;  

  return 0;
}

话虽这么说,但如果我能得到您的共鸣,您将更希望学习它的完成方式,而不是“正确而现代的”答案。

让我们看看您要问的参数。

您需要在一个数组中生成7个随机数,确保没有一个值出现两次。由于选择两次相同的随机数的几率很低(第7个数字为6/40 [15%]),因此我将使用两个循环来进行选择。这将始终有效,并且无需打高尔夫球就能占用最少的内存。

#include <iostream>
#include <random>

using namespace std;

// Those defines could be constants
#define NB_RANDOM_NUMBERS (7)
#define RAND_MODULO (40)

int main()
{
  std::random_device seeder;  // Obtain a seed for the random number engine
  std::mt19937 generator(seeder()); // mersenne_twister_engine seeded with seeder()
  std::uniform_int_distribution<> randomizer(0, RAND_MODULO-1);


  int RandomNumbers[NB_RANDOM_NUMBERS]; // the array that'll get the random numbers

  // A loop for all seven random numbers
  for(int numberIndex = 0; numberIndex < NB_RANDOM_NUMBERS; numberIndex++)
  {
    bool found; // indicates if we found the new number in a previous iteration
    do
    {
      // Generate a new random number
      RandomNumbers[numberIndex] = randomizer(generator);
      /*
      *** If using rand() is required : ***
      RandomNumbers[numberIndex] = rand() % RAND_MODULO;
      */

      // Check if it was found or not in a previous iteration
      found = false;
      for(int checkNumber = 0; checkNumber < numberIndex && !found; checkNumber++)
      {
        // Is the new number already in the array?
        if(RandomNumbers[checkNumber] == RandomNumbers[numberIndex])
        {
          // Exit the loop and restart over
          found = true;
        }
      }
    }
    while(found);

    cout << numberIndex+1 << " : " << RandomNumbers[numberIndex] << std::endl;
  }

  return 0;
}

请注意,NB_RANDOM_NUMBERS-1越接近RAND_MODULO,该算法将运行的时间越长。例如,如果要从100个池中生成90个随机数,则最后一个随机数将有89%的机会已经在RandomNumbers数组中。内部循环可能会运行很长时间,并且算法效率不高。

在这种情况下,填充所有值的数组并随机选择它们会更有效:

#include <iostream>
#include <random>

using namespace std;

#define NB_RANDOM_NUMBERS (7)
#define RAND_MODULO (40)

int main()
{
  std::random_device seeder;  // Obtain a seed for the random number engine
  std::mt19937 generator(seeder()); // mersenne_twister_engine seeded with seeder()
  std::uniform_int_distribution<> randomizer(0, RAND_MODULO-1);

  int RandomNumbers[NB_RANDOM_NUMBERS]; // the array that'll get the random numbers
  int AllValues[RAND_MODULO]; // a array of all numeric values to chose from

  for(int i = 0; i < RAND_MODULO; i++)
  {
    AllValues[i] = i;
  }

  // A loop for all seven random numbers
  for(int numberIndex = 0; numberIndex < NB_RANDOM_NUMBERS; numberIndex++)
  {
    int randomIndex;

    // Search for a random index that doesn't contain -1
    do
    {
      randomIndex = randomizer(generator);
    }
    while(AllValues[randomIndex] == -1);

    // Assign the number at the random index you generated
    RandomNumbers[numberIndex] = AllValues[randomIndex];
    // Set it to -1 in preparation of the next iteration
    AllValues[randomIndex] = -1;

    cout << numberIndex+1 << " : " << RandomNumbers[numberIndex] << std::endl;
  }

  return 0;
}

答案 2 :(得分:0)

我的相同算法的C ++版本。

#include <iostream>
#include <algorithm>
#include <random>
#include <vector>
using namespace std;

int main()
{
    std::random_device rd;
    std::mt19937 g (rd ());

    std::vector <int> v(40);
    std::iota(v.begin(), v.end(), 0);  // Fill the vector with values 0-39

    std::vector<int> output(7);
    std::generate(output.begin(), output.end(),
        [v,g]()mutable
        {
            auto pos = v.begin() + (g()%v.size());    // Pick an element at random (by iterator)
            int value = *pos;                         // Get the value of random element
            iter_swap(pos, v.begin() + v.size() - 1); // Swap the random element to the end of vector
            v.pop_back();                             // Erase the last element of vector (the random element)
            return value;                             // Return the randomly chosen value
        });

    for (auto& x :  output) std::cout << x << '\n';

    return 0;
}

答案 3 :(得分:-1)

这是通过从数组中选择随机元素,然后缩短数组以删除所选元素来实现的。

内嵌评论和解释:

#include <stdio.h>

int main(void) {
    int array[40];
    for(int i=0;i<40; ++i) array[i]=i;  // Fill an array 0-39, in order.

    int output[7];
    for(int i=0; i<7; ++i)
    {
        int rnd_index = rand()%(40-i);    // Pick a random index in the array.
        output[i] = array[rnd_index];     // Copy randomly selected value to the output array
        array[rnd_index] = array[40-i-1]; // Copy the last item in the array to the randomly selected item, effectively removing the selected item from the pool
    }

    // Show the output
    for(int i=0; i<7; ++i) printf("[%d] : %d\n", i, output[i]);
    return 0;
}

输出:

Success #stdin #stdout 0s 9424KB
[0] : 23
[1] : 22
[2] : 3
[3] : 9
[4] : 5
[5] : 10
[6] : 20

请注意,在使用rand()和取模运算时会有轻微的选择偏差。 如果您需要更完美的平面分布,则需要改进。