Boost::accumulators::rolling_mean返回不正确的平均值

boost::accumulators::rolling_mean returning incorrect mean value

本文关键字:不正确 平均值 返回 accumulators rolling Boost mean      更新时间:2023-10-16

环境:VS 2013, Boost 1.58

我已经写了一些东西,为Boost的累加器提供了一个更友好的界面,它可以用来在窗口上投影和,并计算窗口上的实际滚动平均值。在把VS 2013作为我们的主编译器的过程中,这个类的一个单元测试开始失败。剥离图层后,我将其缩小到这个最小的示例:

#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将正确。
  • 一旦窗口满了,如果任何新元素小于它从窗口取出的数字,则rollling_mean将是不正确的。如果它等于或大于,则rolling_mean将是正确的。

这似乎是一个Boost错误,但我想验证我没有做一些愚蠢的事情之前报告错误或试图构建Boost 1.59。提前感谢!

编辑:感谢您的回复,因为这似乎是一个Boost错误。相关的Boost票在这里…这是一个与带累加器的无符号整数相关的问题。具体来说,如果在窗口满后添加到累加器的值严格小于窗口中已经存在的所有值,则调用rolling_mean将返回无效结果。

有一个解决方法,即不将无符号整数与累加器一起使用。这解决了我的问题,所以谢谢你的帮助!

显然有一个bug潜伏在那里,可能在编译器中,但更可能在库中,因为我已经能够在GCC上复制这个:

Live On Coliru

#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/