2015-07-12 2 views
3

У меня есть сбор данных, где в каждой записи есть информация о скорости транспортного средства и времени, когда эта запись была сделана. Разница во времени между каждой записью различна и составляет около 300 мс. Я использую эту коллекцию для расчета пройденного расстояния. Я бы хотел обрезать эту коллекцию без слишком большой потери точности вычислений. Есть ли какой-нибудь алгоритм?Обрезная коллекция, используемая для расчета расстояния

Я попытался написать простой алгоритм, который удалил запись, если запись не отличается от предыдущей, по крайней мере, на X%. Этот алгоритм работает неправильно. Например, когда я использовал алгоритм с 3% и 4% обрезкой, количество записей было таким же, но расчетное расстояние отличалось на 40 м на расстоянии 500 м, где 4% было более точным.

EDIT: Изменения Benjamin алгоритма:

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

double timeDifference = (next.time - curr.time)/(curr.time - previous.time); previuos.value = (previous.value + curr.value * timeDifference)/2

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

+0

Вы можете использовать BigDecimal, если вам нужна точность, но это снизит производительность, но, возможно, это не имеет значения для вас. –

ответ

2

У вас есть список пар значений, т.е .:

time | speed 
1: 0 | 0 
2: 300 | 10 
3: 600 | 40 
4: 900 | 48 
5: 1200 | 50 
6: 1500 | 30 
7: 1800 | 0 

Вы всегда должны смотреть на двух значениях i и i-1. Мы начинаем в i=1, потому что иначе мы бы получить доступ к индексу -1:

for(int i=1; i<list.size(); i++) { 
    if(Math.abs(list.get(i).speed - list.get(i-1).speed) < 3) { 
    list.get(i-1).time = (list.get(i).time + list.get(i-1).time)/2; 
    list.get(i-1).speed = (list.get(i).speed + list.get(i-1).speed)/2; 
    list.remove(i); 
    } 
} 

В словах: Если разница в скорости между i и i-1 меньше 3, а затем обновить запись i-1 и установите время и скорость в среднем от i и i-1. Впоследствии мы удаляем товар i из списка.

Что происходит с примером данных: Этот код удаляет запись 5: из примера данных, так как abs(50-48) = 2 и 2 < 3 и установить запись 4: в time = 1150 и speed = 49

В приведенном выше примере, конечно, имеет по крайней мере два проблемы (которые легко исправить - например, домашняя работа): 1. Если в списке имеется только одна запись, код выдаст исключение. 2. После того, как товар был удален, list.size() изменится, но код, указанный выше, не узнает об этом. Это означает: после удаления любой записи она выдает исключение.

Я не тестировал его, это просто показать вам, как вы можете очистить список.

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

(посмотрите на комментарии ниже)

+0

Хотя я считаю, что это хорошее решение, у меня возникает вопрос: зачем просто '3'? Я имею в виду, это параметр или есть статистически достоверный способ его вычисления на основе имеющихся данных? –

+1

'3', потому что я чувствовал себя как' 3' ;-) Вы можете заменить условие 'if' всем, что вам нравится. Вы также можете рассчитать разницу между обоими значениями в процентах, а затем посмотреть, меньше ли она 20% или что вам нравится. Код должен просто показать, как сравнить два значения из списка, вычислить и установить среднее значение и удалить одну запись. (Btw: 'speed' и' 3' не могут иметь никакого отношения, потому что никто не знает, является ли это km/h, mp/h или seamiles в секунду, или или ...) –

+0

И мое решение довольно плохое, есть много случаев, которые он не обнаружит, и это может привести к плохим данным. ** 1. ** В этом примере он удалит макс. скорость, которая может быть важной. ** 2. ** Когда записи скорости имеют значение «0, 1, 2, 1, 0», результат будет «0,5625», что совершенно бессмысленно. ** 3. ** Было бы гораздо лучше определить, когда ускорение идет вверх или вниз, а затем сохраняют значения max и min, т. Е .: '0, 2, 0'. Эти данные имеют гораздо больше информации! Конечно, это усложняет алгоритм. –

0

Если вам не нужно держать любую историю, вы можете просто обновить пройденное расстояние, когда новые данные извлекаются. Я не знаю, как вы делаете исчисление, я пишу первый пример, который я могу думать.

Measurement record = null; 
double distance = 0; 
long totalTime = 0; 

// New record handler 
public void recordListener(Measurement newRecord) { 
    if(record != null) { 
     double avgSpeed = (record.speed + newRecord.speed)/2.0; 
     long timeDelta = newRecord.time - record.time; 
     distance += avgSpeed * (timeDelta/1000) // millis to seconds 
     totalTime += timeDelta; 
    } 
    record = newRecord; 
} 
+0

Я не могу этого сделать, потому что поток данных выглядит следующим образом: Сбор данных -> Обрезать их -> отправить их на сервер -> Рассчитать расстояние – Amsik

+0

И этот поток выполняется только один раз или регулярно? – Shepard

Смежные вопросы