Модуль VB.NET является статическим классом. Компилятор обрабатывает это для вас. Каждый метод и свойство на нем есть static
(Shared
).
Класс со статическим (Shared) членом является именно таким: класс со статическим (Shared) членом. Вам не нужно создавать его экземпляр для доступа к статическому (Shared) методу, но вам нужно получить доступ к любому из его экземпляров.
Вы также можете определить Sub New()
в модуле, и он станет статическим конструктором для модуля. При первой попытке вызвать элемент в модуле будет вызван статический конструктор для инициализации статического класса.
Я использую результат суммы, к которому я добавляю новые члены и вычитаю старые. Однако таким образом можно страдать от накопления неточностей с плавающей запятой.
Поэтому я реализую "Deque" со списком. И всякий раз, когда мой Deque перераспределяется на меньший размер. Я пересчитываю сумму в том же случае.
Я также вычисляю среднее значение до точки x, включая точку x, так что есть хотя бы одна точка выборки для усреднения.
def getAvgValues(data, avgSampleTime):
lastTime = 0
prevValsBuf = []
prevValsStart = 0
tot = 0
for t, v in data:
avgStart = t - avgSampleTime
# remove too old values
while prevValsStart < len(prevValsBuf):
pt, pv = prevValsBuf[prevValsStart]
if pt > avgStart:
break
tot -= pv
prevValsStart += 1
# add new item
tot += v
prevValsBuf.append((t, v))
# yield result
numItems = len(prevValsBuf) - prevValsStart
yield (t, tot / numItems)
# clean prevVals if it's time
if prevValsStart * 2 > len(prevValsBuf):
prevValsBuf = prevValsBuf[prevValsStart:]
prevValsStart = 0
# recalculate tot for not accumulating float precision error
tot = sum(v for (t, v) in prevValsBuf)
Вы не сказали точно, когда вы хотите вывода. Я предполагаю, что вам нужно одно сглаженное показание для каждого необработанного показания, а сглаженное показание должно быть средним арифметическим необработанного считывания и любых других значений за предыдущие 100 (дельта) секунд.
Краткий ответ: используйте коллекции .deque ... он никогда не будет удерживать больше "дельта" секунд показаний. В соответствии с моей настройкой, вы можете рассматривать двухстороннюю очередь как список и легко вычислять среднее значение или какую-то причудливую штуковину, которая придает больший вес последним показаниям.
Длинный ответ:
>>> the_data = [tuple(map(float, x.split())) for x in """\
... 6 0.738158581
... 21 0.801697222
[snip]
... 251 8.76853608
... 278 9.092367123""".splitlines()]
>>> import collections
>>> delta = 100.0
>>> q = collections.deque()
>>> for t, v in the_data:
... while q and q[0][0] <= t - delta:
... # jettison outdated readings
... _unused = q.popleft()
... q.append((t, v))
... count = len(q)
... print t, sum(item[1] for item in q) / count, count
...
...
6.0 0.738158581 1
21.0 0.7699279015 2
39.0 1.112360133 3
49.0 1.52907127225 4
54.0 1.791208525 5
79.0 2.13137915133 6
91.0 2.49500989771 7
97.0 2.8309395405 8
100.0 3.12993279856 9
118.0 3.74976297144 9
131.0 4.41385300278 9
147.0 4.99420529389 9
157.0 5.8325615685 8
176.0 6.033109419 9
202.0 7.15545189083 6
223.0 7.4342562845 6
251.0 7.9150342134 5
278.0 8.4246097095 4
>>>
Изменить
Один- остановить магазин: достань здесь свою причудливую штуковину. Вот код:
numerator = sum(item[1] * upsilon ** (t - item[0]) for item in q)
denominator = sum(upsilon ** (t - item[0]) for item in q)
gizmoid = numerator / denominator
где ипсилон должен быть немного меньше 1.0 (<= ноль недопустим, чуть выше нуля мало сглаживает, один дает вам среднее арифметическое плюс потраченное впустую время процессора, а больше единицы дает обратное цель).
Ваши данные кажутся примерно линейными:
График ваших данных http://rix0r.nl/~rix0r/share/shot-20090621.144851.gif
Какой вид сглаживания вы ищете? Подгонка линии к этому набору данных методом наименьших квадратов? Какой-то фильтр нижних частот? Или что-то еще?
Сообщите нам приложение, чтобы мы могли посоветовать вам немного лучше.
РЕДАКТИРОВАТЬ: Например, в зависимости от приложения интерполяция линии между первой и последней точкой может быть достаточно хорошей для ваших целей. .
Этот делает его линейным:
def process_data(datafile):
previous_n = 0
previous_t = 0
for line in datafile:
t, number = line.strip().split()
t = int(t)
number = float(number)
delta_n = number - previous_n
delta_t = t - previous_t
n_per_t = delta_n / delta_t
for t0 in xrange(delta_t):
yield previous_t + t0, previous_n + (n_per_t * t0)
previous_n = n
previous_t = t
f = open('datafile.dat')
for sample in process_data(f):
print sample
O (1) память на случай, если вы можете повторить ввод более одного раза - вы можете использовать один итератор для «левого» и один для «правого».
def getAvgValues(makeIter, avgSampleTime):
leftIter = makeIter()
leftT, leftV = leftIter.next()
tot = 0
count = 0
for rightT, rightV in makeIter():
tot += rightV
count += 1
while leftT <= rightT - avgSampleTime:
tot -= leftV
count -= 1
leftT, leftV = leftIter.next()
yield rightT, tot / count
как насчет этого, продолжайте сохранять значения до тех пор, пока разница во времени с последним временем не станет> 100, среднее значение и выдаст такие значения например
def getAvgValues(data):
lastTime = 0
prevValues = []
avgSampleTime=100
for t, v in data:
if t - lastTime < avgSampleTime:
prevValues.append(v)
else:
avgV = sum(prevValues)/len(prevValues)
lastTime = t
prevValues = [v]
yield (t,avgV)
for v in getAvgValues(data):
print v
Похоже, вам нужна простая формула округления. Чтобы округлить любое число до произвольного интервала:
раунд (число / интервал) * интервал
Вы можете заменить раунд на пол или потолок вместо «ведущих до» или «поскольку» влияет. Он может работать на любом языке, включая SQL.
Пока он дает экспоненциально убывающее среднее, а не общее среднее, Думаю, вам может понадобиться то, что я назвал экспоненциальной скользящей средней с изменяющейся альфой , которая на самом деле является однополюсным фильтром нижних частот. Теперь есть решение этого вопроса, и оно выполняется во времени линейно в зависимости от количества точек данных. Посмотрите, сработает ли это для вас.