сжатие чисел с плавающей точкой с указанным диапазоном и точностью - PullRequest
4 голосов
/ 05 декабря 2011

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

Я знаю, что целая часть этих значений будет в диапазоне [-90, 90] и [-180, 180] соответственно. Также у меня есть требование обеспечить фиксированную точность для этих значений (сейчас это 0.00001, но может быть изменено позже).

После изучения типа с плавающей запятой одинарной точности (float) я вижу, что мои значения немного маловаты. Это потому, что 180 * 10^5 больше 2^24 (размер значения и числа с плавающей запятой), но меньше 2^25.

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

Так как я могу выполнить какое-то сжатие при преобразовании моего двойного значения (с фиксированным целочисленным диапазоном частей и указанной точностью X) в байтовый массив в Java? Так, например, если я использую точность из моего примера (0.00001), я получу 5 байтов для каждого значения. Я ищу легкий алгоритм или решение, чтобы он не требовал больших вычислений.

Ответы [ 3 ]

6 голосов
/ 05 декабря 2011

Чтобы сохранить число x с фиксированной точностью (например) 0.00001, просто сохраните целое число, ближайшее к 100000 * x. (Кстати, для этого требуется 26 бит, а не 25, потому что вам также нужно хранить отрицательные числа.)

3 голосов
/ 05 декабря 2011

Как сказал TonyK в его ответ , используйте int для хранения чисел.

Для дальнейшего сжатия чисел используйте locality: Географические координатычасто «слипается» (скажем, очертания городского квартала).Используйте фиксированную контрольную точку (полное разрешение 2x26 бит), а затем сохраните смещения до последней координаты как byte с (дает вам +/- 0,00127).В качестве альтернативы, используйте short, что дает более половины диапазона значений.

Обязательно спрячьте сжатие / декомпрессию в классе, который предлагает только double как внешний API, так что вы можете настроить точностьи алгоритм сжатия в любое время.

2 голосов
/ 05 декабря 2011

Учитывая ваш вариант использования, я бы, тем не менее, использовал double и сжимал их напрямую.

Причина в том, что сильные компрессоры, такие как 7zip , чрезвычайно хороши в обработке "структурированных" данных, которые представляют собой массив типа double (одни данные = 8 байтов, это очень регулярно и предсказуемо) .

Любая другая оптимизация, которую вы можете придумать "от руки", скорее всего будет неполноценной или предложит незначительное преимущество, в то же время стоив вам времени и рисков.

Обратите внимание, что вы все еще можете применить "трюк" преобразования двойного в целое перед сжатием, но я действительно не уверен, принесет ли это вам ощутимую выгоду, в то время как, с другой стороны, это серьезно уменьшит вашу способность справляться с непредвиденные диапазоны цифр в будущем.

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

Итак, подведем итог: я бы предложил прямое сжатие LZMA для вашего массива double.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...