【问题标题】:c++ - How to use <random> to fill std::arrayc++ - 如何使用 <random> 填充 std::array
【发布时间】:2016-12-14 21:59:52
【问题描述】:

我正在尝试生成随机数并将它们填充到数组中的新方法。到目前为止,我已经完成了。

template<size_t SIZE>
void fill_array(array<int, SIZE>& a)
{
    default_random_engine dre;
    uniform_int_distribution<int> uid1(0, 1000);

    for (int i = 0; i < a.size(); i++)
    {
        a[i] = uid1(dre);

    }

}

我的主文件很简单,看起来像这样

    array<int, 10> a;

    Array3 a1;

    a1.fill_array(a);
    a1.print_array(a);

我以为我每次调试时都能得到随机数,但每次都得到相同的数字。很奇怪,有时我确实会得到不同的数字,但同样的事情是我必须多次调试才能获得新的数字。我做错了什么?

【问题讨论】:

  • 如果您想要不确定的结果,请使用std::random_device
  • ... 并初始化例如'std::mt19937',你在你的'std::uniform_int_distribution'中使用。
  • 另外,您不需要编写循环来填充std::array 或任何序列容器。见std::generate
  • 谢谢,我会检查 std::generate 出来的。
  • 为了记录,我承认我本可以更好地提出这个问题的事实。感谢您的帮助。

标签: c++ c++11


【解决方案1】:

即使您使用std::random_device,也不能保证每次都获得不同的序列:

std::random_device 可以根据 实现定义的伪随机数引擎,如果 非确定性源(例如硬件设备)不可用于 实施。在这种情况下,每个 std::random_device 对象可能 生成相同的数列。

例如,在 Windows 上使用较旧的 g++ 实现 stdlibc++ 时会发生这种情况。

此外,由于性能问题,random_device 通常仅用于(一次)播种伪随机位生成器,例如 Mersenne twister 引擎 (std::mt19937)。

您的填充功能可以这样实现:

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

template< class Iter >
void fill_with_random_int_values( Iter start, Iter end, int min, int max)
{
    static std::random_device rd;    // you only need to initialize it once
    static std::mt19937 mte(rd());   // this is a relative big object to create

    std::uniform_int_distribution<int> dist(min, max);

    std::generate(start, end, [&] () { return dist(mte); });
}

int main()
{
    std::array<int, 10> a;

    fill_with_random_int_values(a.begin(), a.end(), 0, 1000);

    for ( int i : a ) std::cout << i << ' ';
    std::cout << '\n';
}

现场演示HERE

【讨论】:

  • 感谢您的回答!我现在对它有了更好的理解。
【解决方案2】:

类似的东西:

#include <random>
#include <array>
#include <algorithm>

template<class Engine, class Integer, size_t SIZE>
void fill_array(Engine& eng, std::array<Integer, SIZE>& a, Integer lower = 0, Integer upper = 1000)
{
    std::uniform_int_distribution<Integer> uid1(lower, upper);

    std::generate(a.begin(), a.end(), [&]
    {
        return uid1(eng);
    });
}

int main()
{
    std::random_device rnd;  // a source of machine-wide entropy
    std::default_random_engine eng(rnd()); // use it to initialise the psuedo-random engine

    std::array<int, 100> arr;
    fill_array(eng, arr);
}

【讨论】:

  • 感谢您的回答! :)
【解决方案3】:

我可以建议使用 std::vector 而不是数组。如果您使用 std::rand 函数,您可以使用srand(time(NULL)); 随时间播种它。当然,您需要为此包含 time.h。您可以在不使用循环的情况下使用generate(a.begin(), a.end(), rand); 填充向量。这每次都会给你一个新的随机数序列。

【讨论】:

  • 感谢您的建议。我一定会记住这一点。 std::generate 非常方便。我实际上是在尝试解决一个练习,所以这就是我使用数组的方法的原因。正如我所注意到的,这可能不是最好的方法。
  • 你仍然可以对数组做同样的事情,只是需要更多的代码。然而,播种随机数生成器才是真正重要的。
【解决方案4】:

您没有将种子初始化为随机值。所以你的随机发生器总是从同一个位置开始。

这是一个如何初始化种子以从某个位置开始的示例。本质上,您需要一些并不总是相同的源,因此您的生成器会产生随机结果,时间是最常用的值。

#include <iostream>
#include <chrono>
#include <random>

int main ()
{
  typedef std::chrono::high_resolution_clock clock;


  std::default_random_engine generator(clock::now().time_since_epoch().count());
  std::uniform_int_distribution<int> rand(0,1000);

  for(int i = 0;i < 10;i++)
 {
    std::cout << rand(generator) << std::endl;
 }

  return 0;
}

【讨论】:

  • 感谢您的回答!
猜你喜欢
  • 2019-07-12
  • 2021-10-30
  • 1970-01-01
  • 1970-01-01
  • 2016-03-12
  • 2019-03-24
  • 1970-01-01
  • 2016-03-24
  • 1970-01-01
相关资源
最近更新 更多