Boost :: аккумуляторы :: Rolling_mean возвращает неправильное среднее значение

Окружающая среда: 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).

Этот код выполняется правильно в VS 2008 с Boost 1.49 (с заменой векторной инициализации C ++ 11, очевидно), но завершается ошибкой в ​​VS 2012 и VS 2013 с Boost 1.58. Я не могу объяснить эту ошибку и поэтому не могу это исправить.

Другие интересные моменты:

  • Ручная проверка значений памяти внутри аккумулятора показывает, что в его циклическом буфере содержатся правильные данные.
  • Если данные, введенные в аккумулятор, упорядочены в порядке возрастания, значение roll_mean будет правильным.
  • Как только окно заполнится, если какой-либо новый элемент будет меньше, чем число, которое он выбивает из окна, roll_mean будет неверным. Если оно равно или больше, значение roll_mean будет правильным.

Кажется, это ошибка Boost, но я хотел убедиться, что я не делаю глупостей, прежде чем сообщать об ошибке или пытаться собрать Boost 1.59. Заранее спасибо!

РЕДАКТИРОВАТЬ: Спасибо за ответы, так как это, похоже, ошибка Boost. Соответствующий Буст Билет Вот.. Это проблема, связанная с целыми числами без знака с аккумуляторами. В частности, если значение, добавленное к аккумулятору после заполнения окна, строго меньше, чем все значения в этом окне, вызов Rolling_mean вернет недопустимый результат.

Существует обходной путь, который не должен использовать целые числа без знака с аккумуляторами. Это решает мою проблему, так что спасибо за помощь!

5

Решение

Там явно скрывается ошибка, возможно, в компиляторе, но, скорее всего, в библиотеке, поскольку я смог воспроизвести это на 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 тип образца`изменение его на подписанное устраняет симптом: Жить на Колиру


Короче: Я бы сообщил об этом в расширенной рассылке или Trac: https://svn.boost.org/trac/boost/

8

Другие решения

Других решений пока нет …