boost::accumulators::rolling_mean 返回不正确的平均值
boost::accumulators::rolling_mean returning incorrect mean value
环境:VS 2013,Boost 1.58
我写了一些东西,为 Boost 的累加器提供了一个更友好的界面,它可用于在 window 上投影总和,并计算 window 上的实际滚动平均值。在推动将 VS 2013 作为我们的主要编译器的过程中,此 class 的单元测试之一开始失败。剥离层,我把它缩小到这个最小的例子:
#include <boost/accumulators/accumulators.hpp>
#include <boost/accumulators/statistics.hpp>
#include <boost/accumulators/statistics/rolling_mean.hpp>
namespace ba = boost::accumulators;
namespace bt = ba::tag;
typedef ba::accumulator_set < uint32_t, ba::stats <bt::rolling_mean > > MeanAccumulator;
int main() {
MeanAccumulator acc(bt::rolling_window::window_size = 5u);
for (uint32_t i : { 3, 2, 1, 0 }) {
acc(i);
std::cout << i << " actualMean: " << std::fixed << boost::accumulators::rolling_mean(acc) << "\n";
}
}
在循环的最后一遍,我没有得到预期的平均值 (1.5),而是得到了一个疯狂的高值 (1431655766.333333)。
此代码在带有 Boost 1.49 的 VS 2008 中正确执行(显然替换了 C++11 向量初始化),但在带有 Boost 1.58 的 VS 2012 和 VS 2013 中失败。我无法解释这个失败,因此无法修复它。
其他有趣的点:
- 手动检查累加器内的内存值表明其循环缓冲区中包含正确的数据。
- 如果放入累加器的数据是递增的,那么rolling_mean就是正确的。
- 一旦 window 已满,如果任何新元素小于它从 window 中剔除的数字,则 rolling_mean 将不正确。如果等于或大于,rolling_mean 将是正确的。
这似乎是一个 Boost 错误,但我想在报告错误或尝试构建 Boost 1.59 之前验证我没有做傻事。提前致谢!
编辑:感谢您的回复,因为这确实是一个 Boost 错误。关联的 Boost 票是 here.。这是一个与带累加器的无符号整数相关的问题。具体来说,如果在 window 满后添加到累加器的值严格小于 window 中的所有值,则 rolling_mean 调用将 return 无效结果。
有一个解决方法,即不对累加器使用无符号整数。这解决了我的问题,非常感谢您的帮助!
显然那里潜伏着一个错误,可能在编译器中,但更有可能在库中,因为我已经能够在 GCC 上重现它:
#include <boost/accumulators/accumulators.hpp>
#include <boost/accumulators/statistics.hpp>
#include <boost/accumulators/statistics/rolling_mean.hpp>
namespace ba = boost::accumulators;
namespace bt = ba::tag;
typedef ba::accumulator_set < uint32_t, ba::stats <bt::rolling_mean > > MeanAccumulator;
int main() {
MeanAccumulator acc(bt::rolling_window::window_size = 5u);
for (uint32_t i : { 252, 189, 248, 154, 620, 885, 939, 196 }) {
acc(i);
std::cout << i << " actualMean: " << std::fixed << boost::accumulators::rolling_mean(acc) << "\n";
}
}
版画
g++-5.2 -std=c++1y -O2 -Wall -pedantic main.cpp && ./a.out
252 actualMean: 252.000000
189 actualMean: 220.500000
248 actualMean: 229.666667
154 actualMean: 210.750000
620 actualMean: 292.600000
885 actualMean: 419.200000
939 actualMean: 569.200000
196 actualMean: 858994018.000000
现在问题似乎与 选择 unsigned
样本类型有关`:将其更改为已签名可消除症状:Live On Coliru
简而言之:我会在 boost 邮件列表或 Trac 中报告此事:https://svn.boost.org/trac/boost/
环境:VS 2013,Boost 1.58
我写了一些东西,为 Boost 的累加器提供了一个更友好的界面,它可用于在 window 上投影总和,并计算 window 上的实际滚动平均值。在推动将 VS 2013 作为我们的主要编译器的过程中,此 class 的单元测试之一开始失败。剥离层,我把它缩小到这个最小的例子:
#include <boost/accumulators/accumulators.hpp>
#include <boost/accumulators/statistics.hpp>
#include <boost/accumulators/statistics/rolling_mean.hpp>
namespace ba = boost::accumulators;
namespace bt = ba::tag;
typedef ba::accumulator_set < uint32_t, ba::stats <bt::rolling_mean > > MeanAccumulator;
int main() {
MeanAccumulator acc(bt::rolling_window::window_size = 5u);
for (uint32_t i : { 3, 2, 1, 0 }) {
acc(i);
std::cout << i << " actualMean: " << std::fixed << boost::accumulators::rolling_mean(acc) << "\n";
}
}
在循环的最后一遍,我没有得到预期的平均值 (1.5),而是得到了一个疯狂的高值 (1431655766.333333)。
此代码在带有 Boost 1.49 的 VS 2008 中正确执行(显然替换了 C++11 向量初始化),但在带有 Boost 1.58 的 VS 2012 和 VS 2013 中失败。我无法解释这个失败,因此无法修复它。
其他有趣的点:
- 手动检查累加器内的内存值表明其循环缓冲区中包含正确的数据。
- 如果放入累加器的数据是递增的,那么rolling_mean就是正确的。
- 一旦 window 已满,如果任何新元素小于它从 window 中剔除的数字,则 rolling_mean 将不正确。如果等于或大于,rolling_mean 将是正确的。
这似乎是一个 Boost 错误,但我想在报告错误或尝试构建 Boost 1.59 之前验证我没有做傻事。提前致谢!
编辑:感谢您的回复,因为这确实是一个 Boost 错误。关联的 Boost 票是 here.。这是一个与带累加器的无符号整数相关的问题。具体来说,如果在 window 满后添加到累加器的值严格小于 window 中的所有值,则 rolling_mean 调用将 return 无效结果。
有一个解决方法,即不对累加器使用无符号整数。这解决了我的问题,非常感谢您的帮助!
显然那里潜伏着一个错误,可能在编译器中,但更有可能在库中,因为我已经能够在 GCC 上重现它:
#include <boost/accumulators/accumulators.hpp>
#include <boost/accumulators/statistics.hpp>
#include <boost/accumulators/statistics/rolling_mean.hpp>
namespace ba = boost::accumulators;
namespace bt = ba::tag;
typedef ba::accumulator_set < uint32_t, ba::stats <bt::rolling_mean > > MeanAccumulator;
int main() {
MeanAccumulator acc(bt::rolling_window::window_size = 5u);
for (uint32_t i : { 252, 189, 248, 154, 620, 885, 939, 196 }) {
acc(i);
std::cout << i << " actualMean: " << std::fixed << boost::accumulators::rolling_mean(acc) << "\n";
}
}
版画
g++-5.2 -std=c++1y -O2 -Wall -pedantic main.cpp && ./a.out
252 actualMean: 252.000000
189 actualMean: 220.500000
248 actualMean: 229.666667
154 actualMean: 210.750000
620 actualMean: 292.600000
885 actualMean: 419.200000
939 actualMean: 569.200000
196 actualMean: 858994018.000000
现在问题似乎与 选择 unsigned
样本类型有关`:将其更改为已签名可消除症状:Live On Coliru
简而言之:我会在 boost 邮件列表或 Trac 中报告此事:https://svn.boost.org/trac/boost/