密度计算中的错误 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
似乎 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