2015-05-14 7 views
0

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

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

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

+0

Будете ли вы хранить больше, чем те 10 с данных в векторе? Если нет, вы можете рассматривать это как круговой буфер. Затем вы можете просто вычислить сумму всего вектора. Когда вы добавляете новые элементы, вам нужно начинать добавлять в начале, как только вы достигнете конца. Если у вас нет кругового буфера, вы просто получаете итератор к последнему элементу и вычисляете сумму элементов из него до 10 сек. Назад (в зависимости от количества элементов). – rozina

ответ

0

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

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

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

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

Хранить количество элементов и рассчитать среднее значение.

1

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

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; 
+0

Как это гарантировать, что у меня средний показатель за последние 10 секунд? – anikomei

+0

@anikomei Вы должны знать, сколько образцов вы измеряете за 10 секунд. – rozina