密度计算中的错误 std::piecewise_constant_distribution?

Bug in density calculation std::piecewise_constant_distribution?

似乎 std::piecewise_constant_distribution 错误地计算了密度,至少 GCC 及其标准库是这样。

根据http://www.cplusplus.com/reference/random/piecewise_constant_distribution/: 密度应计算为:

手动检查发现错误!

可以在这里看到:http://coliru.stacked-crooked.com/a/ca171bf600b5148f

与此相关的源代码在/usr/include/c++/4.8/bits/random.tcc(在linux)中找到,构造函数调用的初始化函数_M_initialize的摘录表明这里有一些不正确的地方:

const double __sum = std::accumulate(_M_den.begin(),
                       _M_den.end(), 0.0);

      __detail::__normalize(_M_den.begin(), _M_den.end(), _M_den.begin(),
                __sum);  <----- WRONG

      // THIS is not the cummulative distribution (since the above normalization does not give the probability of the intervalls!)
      _M_cp.reserve(_M_den.size());
      std::partial_sum(_M_den.begin(), _M_den.end(),
               std::back_inserter(_M_cp));


      // Make sure the last cumulative probability is one.
      _M_cp[_M_cp.size() - 1] = 1.0;



      // Dividing here by the interval length is WRONG!!!

      for (size_t __k = 0; __k < _M_den.size(); ++__k)
           _M_den[__k] /= _M_int[__k + 1] - _M_int[__k];

cplusplus.com 上的措辞含糊不清。 cppreference.com给出了更清晰的解释,而这正是C++标准中所写的:

这是规范的适用部分,直接来自 N4296:

可以清楚地看到,求和仅适用于权重。

很容易看出你的测试代码有问题。将间隔数减少为两个,第一个长度为 1,第二个长度为 2:

std::array<PREC,3> intervals {0, 1, 3};

并赋予每个区间权重等于它的长度:

std::array<PREC,2> weights   {1, 2};

人们会期望密度是恒定的。但是 your code reports:

Probability : 0.200000000000000011102230246252
Probability : 0.400000000000000022204460492503