2015-10-05 78 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