Существует эффективный способ отслеживания минимального (или максимального) значения в заданном временном окне без обычно необходимо хранить все числа, которые попали в это окно. (Тем не менее, в худшем случае все еще требуется хранить все номера, поэтому вам необходимо зарезервировать место для всех или принять, что иногда вы можете получить неправильные результаты.)
Хитрость заключается в сохранении значений, которые:
- прибыли в пределах временного окна, и
- меньше (или больше), чем любое более позднее значение.
Подходящая структура данных для реализации представляет собой простой кольцевой буфер, сохраняющий значения и время их поступления. Вам нужно будет поддерживать два индекса в буфере. Вот простой английское описание алгоритма:
При запуске:
- Выделяет N -элементного буфер
val
значений и соответствующий N -элементного буфер time
меток времени.
- Пусть
imax
= 0 (или любое другое значение между 0 и Н − 1 включительно), и пусть inext
= imax
. Это означает, что буфер в настоящее время пуст.
Когда новое значениеnew
принимается во времяt
:
- В то время как
imax
≠ inext
и time[imax]
находится вне интервала, приросте imax
по одному (по модулю N) ,
- В то время как
imax
≠ inext
и val[inext-1]
≥ new
, декремент inext
на единицу (по модулю N ).
- Факс:
val[inext]
= new
и time[inext]
= t
.
- Если
inext
≠ imax-1
, приращение inext
на единицу (по модулю N ); иначе примените условие «полное заполнение буфера» (например, выделите больший буфер, выбросьте исключение или просто проигнорируйте его и примите, что последнее значение было неправильно записано).
Когда запрашивается минимальное значение:
- В то время как
imax
≠ inext
и time[imax]
находится вне интервала, приращение imax
на единицу (по модулю N ).
- If
imax
≠ inext
, return val[imax]
; else вернет ошибку, указывающую, что никакие значения не были получены в течение временного интервала.
Если значения, полученные независимы и одинаково распределены (и прибывают как пуассоновский процесс), я считаю, что можно показать, что среднее число значений, сохраненных в списке в любой данный момент времени п (п +1), где n - среднее число значений, полученных в течение интервала времени. Для n = 50 000, ln (n +1) & approx; 10,82. Однако следует иметь в виду, что это только среднее значение, и иногда может потребоваться несколько раз больше места.
Для среднего, тот же трюк, к сожалению, не работает. Если возможно, вы можете переключиться на exponentially moving average, который можно легко отследить, используя очень мало места (только одно число для средней и одной отметки времени, указывающее, когда оно было последним).
Если это невозможно, но вы готовы принять небольшое количество сглаживания в средних значениях, вы можете рассчитать среднее значение, скажем, каждую миллисекунду. Таким образом, всякий раз, когда запрашивается среднее значение значений за последнюю секунду, вы можете просто взять среднее значение из последних средних значений 1001 миллисекунды, взвешивая самые старые и новейшие из них в зависимости от того, сколько из этих миллисекунд находится в интервале:
При запуске:
- Пусть интервала быть длиной временного интервала усреднения над, и пусть п быть числом подынтервалов.
- Пусть дт = интервал/п.
- Выделяют п +1 -элементного буфер
sum
значений и п +1 -элементного буфер cnt
неотрицательных целых чисел, и заполнить оба с нулями.
- Пусть
prev
имеют любую ценность. (Это на самом деле не имеет значения.)
Когда новое значениеnew
принимается во времяt
:
- Пусть
i
= пол (t
/дт) мод (n +1).
- Если
i
≠ prev
:
- Вычесть
sum[i]
из total
и cnt[i]
от count
.
sum[i]
= 0, cnt[i]
= 0 и prev
= i
.
- Добавить
new
в sum[i]
и прирастить cnt[i]
.
- Добавить
new
в total
и прирастить count
по одному.
Когда среднее значение запрашивается во времяt
:
- Пусть
i
= пол (t
/DT) мод (п +1).
- Если
i
≠ prev
:
- Вычесть
sum[i]
из total
и cnt[i]
от count
.
- Let
sum[i]
= 0, cnt[i]
= 0, и пусть prev
= i
.
- Пусть
j
= (i
− п) мод (п +1) = (i
+ 1) мод (п +1).
- Пусть
w
= гидроразрыва (t
/дт) = (t
/DT) − этаж (t
/дт).
- Return (
total
− w
× sum[j]
)/(count
− w
× cnt[j]
).
Можете ли вы гарантировать, что цифры прибывают в порядок? –
вы говорите, что «примерно 50 000» могут варьироваться или вы не уверены в #? – n8wrl
Он может меняться, данные поступают из внешнего компонента ... – Dusan