【问题标题】:Generate random number and guaranteed to cover all between the given domain? [closed]生成随机数并保证覆盖给定域之间的所有? [关闭]
【发布时间】:2019-05-14 07:34:32
【问题描述】:

有人可以帮我生成 0-71 之间的随机数,同时保证它会覆盖从 0 到 71 的所有数字吗?

我尝试了以下方法,但有些数字出现了不止一次,有些则根本不出现。

int max= 71;
int min= 0;

std::random_device engine;

//initialise to -1 to make sure numbers are generated and stored properly
int randomNum = -1;

while(max> 0){
  std::uniform_int_distribution<int> randomDistributed(min,max);
  randomNum = randomDistrubuted(engine);
  std::cout << randomNum << ", ";
  max--;
}

更新:这个问题是因为我打算生成随机数而提出的,所以我可以打乱我自己的 LinkedList 数据结构的实现。我希望通过创建一个新列表并将 oldList->get(randomNumber) 元素中的元素添加到新的随机列表中来实现这一点。上面的代码实际上应该足以实现这一点,正如前面提到的当前句之前的最后一句。

【问题讨论】:

  • 将数字存储在 unordered set 中,直到集合中有 73 个元素?
  • std::random_shuffle 一组 [0..72] 并打印出来。
  • @Botje 他希望 72 也能加入 -> (0,73)
  • 只要您的自定义 ADT 有迭代器就可以了。另一种选择:在[0..limit]中选择一个随机数i,输出numbers[i](最初只是[0..72]),交换numbers[i]numbers[limit],并减少limit。重复直到limit &lt; 0
  • 这里有什么问题吗,还是我们可以假设原来的问题已经解决了?

标签: c++ random


【解决方案1】:

如果您已经为您的链表类编写了迭代器,则可以调整 possible implementationsstd::shuffle 中的一个以对前向迭代器进行操作。

#include <iostream>
#include <list>
#include <random>
#include <algorithm>
#include <iterator>

template<class ForwardIt, class URBG>
void list_shuffle(ForwardIt first, ForwardIt last, URBG&& g)
{
    using diff_t = typename std::iterator_traits<ForwardIt>::difference_type ;
    using distr_t = std::uniform_int_distribution<diff_t>;
    using param_t = typename distr_t::param_type;
    using std::iter_swap;

    distr_t distr;
    diff_t n = std::distance(first, last);
    for (diff_t i = n - 1; i > 0; --i)
    {
        auto it = std::next(first, distr(g, param_t(0, i)));
        iter_swap(first++, it);
    }
}

int main() 
{
    std::random_device rd;
    std::mt19937 g(rd());
    std::list<int> a {1, 2, 3, 4, 5, 6, 7};


    list_shuffle(a.begin(), a.end(), g);

    for (auto const & i : a)
        std::cout << ' ' << i;
    std::cout << '\n';
}

不过,这会非常低效,因此您可能更愿意将列表复制到向量中,将其打乱并从中重新创建列表。

【讨论】:

  • 我打算生成随机数,这样我就可以打乱我自己的 LinkedList 数据结构的实现。我希望通过创建一个新列表并将 oldList->get(randomNumber) 元素中的元素添加到新的随机列表中来实现这一点。希望这能消除一些疑虑。
  • @ChanbothSom 好的,所以你必须知道列表的大小 n,然后在 0 和 n 之间选择一个数字 k。使用std::list,您可以将迭代器推进 k 次,将新列表中的值 push_front 并从源列表中删除该元素。之后,只需减少 n 并重复。如何使用您自己的类执行此操作取决于您如何实现它。
【解决方案2】:

此代码生成 1000 个随机数。标准函数 srand() 通过“种子”为 rand() 生成随机序列,并将其作为参数。 time() 函数采用当前时间,因此每个时间序列都是唯一的。

#include <random>
#include <ctime>
#include <vector>

using std::vector;

int main() {
    srand(time(0));
    vector<int> v;
    for (int i = 0, num = 0; i < 1000; ++i) {
        num = rand()%72;
        v.push_back(num);
    }
}

【讨论】:

  • 它和OP有同样的问题,但是:随机数生成器可能会产生重复的数字,所以只覆盖了部分范围。
  • 那么,为什么我们还需要随机生成器呢?如果我们需要该范围内的所有数字,只有一个重复,我们需要随机数吗?
  • OP 的程序显示了生成数字 [0..72] 的随机排列的意图
  • 我打算生成随机数,这样我就可以打乱我自己的 LinkedList 数据结构的实现。我希望通过创建一个新列表并将 oldList->get(randomNumber) 元素中的元素添加到新的随机列表中来实现这一点。希望这能消除一些疑虑。
猜你喜欢
  • 2012-07-06
  • 2017-11-06
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-07-31
  • 1970-01-01
  • 2023-04-01
  • 1970-01-01
相关资源
最近更新 更多