Вычисление скользящего среднего потока значений, хранящихся в векторе

У меня есть вектор структур, который хранит поток значений, которые поступают через разные промежутки времени. Структура состоит из двух элементов, один для значения, а другой записывает время прибытия значения.

struct Data {
Time timeOfArrival;
Time value;
}cd;

Допустим, в другом потоке я хочу вычислить скользящее среднее значений, полученных за последние 10 (скажем) секунд. Итак, в одном потоке заполняется вектор, а в другом я хочу вычислить скользящее среднее.

0

Решение

Вот как бы я это сделал. Для простоты я переопределил данные следующим образом:

struct Data
{
int timeOfArrival;
int value;
};

Один из способов сделать то, что вы просили, — это использовать кольцевой буфер, в котором вы храните только тот объем данных, который вам нужен для вашего скользящего среднего.

enum { MOVING_AVG_SIZE = 64, };  // number of elements that you use for your moving average

std::vector<Data> buffer(MOVING_AVG_SIZE);
std::vector<Data>::iterator insertIt = buffer.begin();

// saving to circular buffer
Data newData;

++insertIt
if (insertIt == buffer.end()) insertIt = buffer.begin();
*insertIt = newData;

// average
int sum = 0;
for (std::vector<Data>::const_iterator it = buffer.begin(); it != buffer.end(); ++it)
{
sum += it->value;
}
float avg = sum / (float)buffer.size();

Если у вас нет кругового буфера, и вы просто продолжаете добавлять значения к вектору, тогда вы можете просто получить последнее количество элементов, необходимое для вычисления скользящего среднего.

// saving to circular buffer
Data newData;
buffer.push_back(newData);

// average
// this algorithm calculates the moving average even if there is not enough samples in the buffer for the "10 s"std::vector<Data>::const_reverse_iterator it = buffer.rbegin();
int i;
int sum = 0;
for (i = 0; i < MOVING_AVG_SIZE || it == buffer.rend(); ++i)
{
sum += it->value;
}
float avg = sum / (float)i;
1

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

Как вы уже решили, что один поток будет всегда заполняться, а другой поток будет выполнять скользящее среднее. Затем вы можете сделать это:

Сохраняйте структуру с двумя элементами RunningSum и без элементов в векторе.

Напишите цикл, который удаляет элементы старше 10 секунд и вычитает их значения из RunningSum. Все элементы в векторе отсортированы по времени Arrival, поэтому вам не нужно перебирать весь вектор.
Добавьте к сумме стоимость новых elemnts, которые еще не добавлены.

Вам нужен способ разграничить элементы, которые были добавлены (использованы в сумме), и тот, который еще не суммирован. Вы можете использовать логическое значение для этого или поместить их в новую dataStructure (внутреннюю для вашего класса).

Ведите подсчет количества элементов и рассчитайте среднее.

0

По вопросам рекламы [email protected]