【问题标题】:Why c++11 std::normal_distribution return same pattern when called from a function?为什么从函数调用时 c++11 std::normal_distribution 返回相同的模式?
【发布时间】:2018-09-20 05:16:51
【问题描述】:

我想将高斯噪声引入信号。我研究了几个如何使用 C++11 std::normal_distribution 的示例,我能够使用此示例实现预期的随机结果:https://stackoverflow.com/a/32890945/3424478

#include <functional>
#include <iostream>
#include <iterator>
#include <random>

int main() {
    // Example data
    std::vector<double> data = {1., 2., 3., 4., 5., 6.};

    // Define random generator with Gaussian distribution
    const double mean = 0.0;
    const double stddev = 0.1;
    auto dist = std::bind(std::normal_distribution<double>{mean, stddev},
                          std::mt19937(std::random_device{}()));

    // Add Gaussian noise
    for (auto& x : data) {
        x = x + dist();
    }

    // Output the result, for demonstration purposes
    std::copy(begin(data), end(data), std::ostream_iterator<double>(std::cout, " "));
    std::cout << "\n";

    return 0;
}

当我从main() 多次调用dist() 时,这非常有效,并且在不同的向量上也可以正常工作,但是一旦我将代码移动到一个函数,它总是返回相同的恒定噪声模式,我想称之为函数来修改参考信号并将其分配给不同的数组或向量。这是我的代码:

void AddGaussianNoiseToPixel(std::array<short int, N_SLICES>& pixel_array, const std::array<short int, N_SLICES>& reference_pixel)
{
    const float mean   = 0.0;
    const float stddev = 2.0;
    auto dist = std::bind(std::normal_distribution<float>{mean, stddev},
                          std::mt19937(std::random_device{}()));

    for (const auto& slice : reference_pixel) 
    {
        pixel_array[&slice-&reference_pixel[0]] = rint(slice+dist());
    }
}

我读到了类似的帖子:https://stackoverflow.com/a/22921927/3424478,这可能是由于种子传递给了随机生成器,但事实并非如此,因为我将std::random_device{}() 传递给随机引擎std::mt19937()

编辑:

我在 Windows 7 中使用 MinGW-W64-builds-4.3.5

【问题讨论】:

  • 什么平台和编译器?
  • 这是在使用 MinGW 吗?
  • 另外std::bind 比使用lambda 慢。此外,每次调用函数时创建和初始化随机生成器的效率都会低于一次初始化随机生成器并将其传递给函数。
  • 不要在每次调用函数时创建新的生成器和分布。使用静态变量。
  • 来自cppreference:如果非确定性源(例如硬件设备)对实现不可用,则可以根据实现定义的伪随机数引擎来实现 std::random_device . 在这种情况下,每个 std::random_device 对象都可以生成相同的数列

标签: c++ c++11 random normal-distribution


【解决方案1】:

这很可能与使std::random_device 具有确定性的feature/bug in mingw 有关。您可以通过添加另一个熵源来规避这一点,例如当前时间:

  uint64_t seed = std::random_device{}() |
    std::chrono::system_clock::now().time_since_epoch().count();

但是,更好的解决方案是仅使用一个引擎和分发对象。一种简单的方法是在新函数中使用静态变量。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2020-12-29
    • 1970-01-01
    • 1970-01-01
    • 2017-03-04
    • 2017-10-13
    • 2012-10-17
    • 1970-01-01
    • 2011-09-06
    相关资源
    最近更新 更多