【问题标题】:make a list of different random integers less than ten制作一个小于十的不同随机整数的列表
【发布时间】:2019-08-07 04:31:51
【问题描述】:

我想生成一个小于 10 的随机整数列表,它们不一样(不同的整数),例如(0,3,1,5,8)。 但是我写的代码有问题,前两个整数总是相同的。 如果你的代码告诉我我的代码的错误或提供另一种方法来做到这一点,那就太好了。

vector<int> rand_list(10, 11); //there is ten integers of 11   
for (int i = 0; i < 5; i++) // here we make 5 different integers
{
    srand(time(NULL));
    int r = rand() % 10;
    int check = 0;
    for (check; check <= i; check++)
    {
       if (r == rand_list[check])
       {
         srand(time(NULL));
         r = rand() % 10;
         check = 0;//I think this line don't force the second loop for to start again.
       }
    }
    rand_list[i] = r;
}

这里我希望 rand_list 有 5 个不同的整数,其他项目必须是 11,但前两个整数总是相同的!

【问题讨论】:

  • 您可能想在开始之前播种一次。
  • You may find std::shuffle 在分配要求没有禁止的情况下在这里很有用。如果他们有,请窃取这个想法。
  • 你也可以简单地用0..10填充一个向量v,然后,5次,在0..v.size()-1中选择一个随机索引,将该索引处的值添加到你的结果中,然后删除它向量中的元素。

标签: c++ random


【解决方案1】:

不要多次致电srand()time() 具有秒精度,因此在同一秒内以 time() 为种子多次调用 srand() 将导致 rand() 每次返回相同的数字,这不是您想要发生的。只调用一次srand(),例如在程序启动时。

更好的是,根本不要使用 C 运行时的随机数生成器。请改用标准 C++ 随机数生成器。

至于您的算法,一个更简单的解决方案是将连续数字 0-9 放入一个数组中,然后运行一个循环,在该数组中生成一个随机索引并删除该元素以放入您的向量中,重复直到所有数组元素用尽,例如:

#include <algorithm>
#include <random>

std::random_device rd;
std::mt19937 gen(rd());

std::vector<int> rand_list(10);

int numbers[10];
std::generate_n(numbers, 10, [n = 0]() mutable { return n++; });
int avail = 10;

for (int i = 0; i < 10; i++) {
    std::uniform_int_distribution<> dis(0, avail-1);  
    int r = dis(gen);
    rand_list[i] = numbers[r];
    std::copy(&numbers[r+1], &numbers[avail], &numbers[r]);
    --avail;
}

Live Demo

或者更简单,你可以使用标准的std::shuffle()算法来代替,例如:

#include <algorithm>
#include <random>

std::random_device rd;
std::mt19937 gen(rd());

std::vector<int> rand_list(10);
std::generate_n(rand_list.begin(), 10, [n = 0]() mutable { return n++; });
std::shuffle(rand_list.begin(), rand_list.end(), gen);

Live Demo

【讨论】:

    【解决方案2】:

    在程序开始时只使用一次srand()
    然后,从一系列值中获取不同随机数的一种简单方法是, 从尚未使用的数字集中抽取一个随机数。

    • 填充您的一组数字(例如,填充到向量中)。
    • (重复,例如 5 次):为您的一组数字生成一个随机索引。
      然后打印该索引处的数字。
      然后从您的未使用数字集中删除该索引处的数字。

    这样,您无需重试并检查该号码是否已被使用。 由于std::vector&lt;T&gt;::erase(const_iter it) 不是O(1)std::vector&lt;T&gt; 可能不是最佳的数据结构。理想情况下,您需要一个允许在O(1) 中建立索引并在O(1) 中擦除的数据结构。

    
    #include <cstdint>
    #include <cstdlib>
    #include <ctime>
    #include <vector>
    #include <cstdio>
    
    int main(int argc, const char* argv[] )
    {
        using UI16Vec = std::vector<uint16_t>;
        UI16Vec numbers;
        srand(time(NULL));
        // Fill in your range of numbers.
        numbers.reserve(10);
        for(  uint16_t i = 0; i < 10; i++ )
        {
             numbers.push_back(i);
        }
        // Pick and remove from numbers.
        for( size_t i = 0; i < 5; i++ )
        {
             size_t index = rand() % numbers.size();
             printf("%d: %d\n", i, numbers[index] );
             numbers.erase(numbers.cbegin() + index);
        }
        return 0;
    }
    
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2012-12-15
      • 2012-02-10
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-12-27
      相关资源
      最近更新 更多