【问题标题】:Unexpected behaviour of std::discrete_distributionstd::discrete_distribution 的意外行为
【发布时间】:2014-02-23 19:05:27
【问题描述】:

我正在使用 Visual Studio 2013(调试模式),它没有 std::discrete_distribution 的基于迭代器的构造函数,因此我使用了一种解决方法。但是,使用此解决方法时,如果最后一个元素不大于 weights 中的第一个元素,则会产生运行时错误。

使用初始化列表时不会产生此错误。

例子:

#include <iostream>
#include <random>
#include <vector>

int main(){
    std::discrete_distribution<> dist1 = { 10.f,11.f,5.f };

    std::cout << "!" << std::endl;

    std::vector<float> weights = { 10.f, 11.f, 5.f};

    std::size_t i(0);

    std::discrete_distribution<> dist2(weights.size(), weights.front(), weights.back(),
        [&weights, &i](double){
        auto w = weights[i];
        ++i;
        return w;
    });

    std::cout << "!!" << std::endl;

    return 0;
}

输出:

discrete_distribution 的范围无效

weights 的末尾添加任何大于 10 的数字将停止运行时错误的发生。

为什么会这样?

【问题讨论】:

    标签: c++ algorithm math random std


    【解决方案1】:

    您正在使用here 描述的第三个构造函数,即:

    template< class UnaryOperation >
    discrete_distribution( std::size_t count, double xmin, double xmax,
                           UnaryOperation unary_op );
    

    std::discrete_distribution 实例的正确初始化需要这样做

    delta * 2 = (xmax - xmin) &gt; 0.

    【讨论】:

    • @pighead10 还有什么需要解释的吗?
    • 对。那么除了对向量进行重新排序之外,有没有办法避免这种情况?
    • 你可以直接指定 xmin 和 xmax 并将它们传递给discrete_distribution 构造函数,但你还必须确保用你的一元谓词构造的权重是正确的
    • 哦,是的,我忘记了我使用 .front() 和 .back() 作为最小值和最大值,而它们实际上并不是最小值和最大值!谢谢。
    【解决方案2】:

    对于此解决方法,您的 lambda 实际上并未使用 xmin 和 xmax(或 fw 的结果)来计算权重,因此不必担心重新排序数组。只需传递 0 和 1(或 xmin

    std::discrete_distribution<> dist2(weights.size(), 0, 1,
        [&weights, &i](float){
        auto w = weights[i];
        ++i;
        return w;
    });
    

    示例:http://ideone.com/351Jhg

    【讨论】:

      最近更新 更多