使用std ::用std :: normal_distribution和std :: bind

Using std::transform with std::normal_distribution and std::bind

本文关键字:std distribution bind normal 使用      更新时间:2023-10-16

stl c 11解决方案:

auto distribution = std::bind(std::normal_distribution<double>{mean, stddev},
                              std::mt19937(std::random_device{}())
                              );
std::transform(data.begin(), data.end(), data.begin(),
               std::bind(std::plus<double>(), std::placeholders::_1, distribution()));

易于基于范围的循环:

for (auto& d : data) {
  d += distribution();
}

我的STL解决方案不起作用,因为它总是从发行版中生成的第一个数字。我尝试以占位符为第三参数,但不会改变任何内容。我的所有数据都被相同的数字增加,这不是我想要的。我想要与基于范围的循环相同的行为。

这可能是可能的?

让我们将第二个bind作为lambda重写,以使感觉它的实际工作方式:

auto func = std::bind(std::plus<double>(), std::placeholders::_1, distribution())

是等效的

auto d = distribution();
auto func = [d](double x){ return std::plus<double>()(x,d); };

或,如果我们使用C 14的初始化功能:

auto func = [d=distribution()](double x){ return std::plus<double>()(x,d); };

如您所见,distribution()仅被调用一次。但是,您不想使用distribution的返回值,而是要在func的每个呼叫中调用distribution。虽然可以使用bind来做到这一点,但lambda会使此操作变得容易得多:

std::transform(data.begin(), data.end(), data.begin(),
               [&distribution](double x){ return x + distribution(); });

我认为,这比您以前的bind容易得多。请注意,std::bind(或boost::bind)早于Lambdas。与std::bind相比,C 11中的Lambdas有一些问题,但是C 14,Lambdas通常更容易处理,阅读和理解而不牺牲太多。