2015-10-05 76 views
4

环境:VS 2013,升压1.58的boost ::蓄电池:: rolling_mean返回不正确平均值

我写的东西,提出了一个更友好的界面来提高的蓄能器,它可以用来预测在一个总和窗口,并计算窗口上的实际滚动平均值。在推进到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)。

此代码在VS 2008中以Boost 1.49正确执行(显然,C++ 11矢量初始化被替换),但在VS 2012和VS 2013中失败且升级1.58。我无法解释这种失败,因此无法解决这个问题。

其它有趣的点:

  • 手动检查存储器内的值累加器揭示了正确的数据被包含在它的循环缓冲器。
  • 如果放入累加器的数据按递增值排序,那么rolling_mean将是正确的。
  • 一旦窗口已满,如果任何新元素小于它从窗口中敲出的数字,那么rolling_mean将不正确。如果它相同或更大,rolling_mean将是正确的。

它似乎是一个Boost错误,但是想要在报告错误或尝试构建Boost 1.59之前验证我没有做什么愚蠢的事情。提前致谢!

编辑:感谢您的回应,因为这看起来似乎是一个助推器的错误。相关的Boost票据是here.。这是一个与带累加器的无符号整数有关的问题。具体来说,如果窗口已满后添加到累加器的值严格小于窗口中的所有值,那么rolling_mean调用将返回无效结果。

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

+1

看看你的位模式:它是ccccccccc/4。再加上一点。这是未初始化的堆栈内存。调试升压代码,直到看到一个cccccccc读取也许。 – Yakk

+0

我刚和一位同事讨论这个问题。谢谢你的提示!我会看看它。 – iamtheddrman

+1

下面是一个大大简化的样本,展示了GCC(4.8-5.2)的问题:** [Live On Coliru](http://coliru.stacked-crooked.com/a/1fb8265aaac32e12)** – sehe

回答

7

有明显的库编译潜伏在那里,可能是一个错误,但更可能的,因为我已经能够重现这对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 

现在问题出现了RS将相关选择unsigned样品type`:将其更改为签署消除症状:Live On Coliru


总之:我会在boost邮件列表报告此或Trac:https://svn.boost.org/trac/boost/

+3

这可能已经存档在trac中:https://svn.boost.org/trac/boost/ticket/11437 –

+0

如果你问我的话,它会打中所有的复选框。我无法在家用工作站(o.O)重新制作这个文件,所以我自己找不到修复程序。谢谢你们在那里做点工作。 – sehe