У меня есть вектор структур, который хранит поток значений, которые поступают через разные промежутки времени. Структура состоит из двух элементов, один для значения, а другой записывает время прибытия значения.
struct Data {
Time timeOfArrival;
Time value;
}cd;
Допустим, в другом потоке я хочу вычислить скользящее среднее значений, полученных за последние 10 (скажем) секунд. Итак, в одном потоке заполняется вектор, а в другом я хочу вычислить скользящее среднее.
Вот как бы я это сделал. Для простоты я переопределил данные следующим образом:
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;
Как вы уже решили, что один поток будет всегда заполняться, а другой поток будет выполнять скользящее среднее. Затем вы можете сделать это:
Сохраняйте структуру с двумя элементами RunningSum и без элементов в векторе.
Напишите цикл, который удаляет элементы старше 10 секунд и вычитает их значения из RunningSum. Все элементы в векторе отсортированы по времени Arrival, поэтому вам не нужно перебирать весь вектор.
Добавьте к сумме стоимость новых elemnts, которые еще не добавлены.
Вам нужен способ разграничить элементы, которые были добавлены (использованы в сумме), и тот, который еще не суммирован. Вы можете использовать логическое значение для этого или поместить их в новую dataStructure (внутреннюю для вашего класса).
Ведите подсчет количества элементов и рассчитайте среднее.