Алгоритм сжатия для данных IEEE 754

У кого-либо есть рекомендация на хорошем алгоритме сжатия, который работает хорошо со значениями с плавающей точкой двойной точности? Мы нашли, что двоичное представление значений с плавающей точкой приводит к очень недостаточным уровням сжатия с общими программами сжатия (например, Zip, RAR, С 7 zip и т.д.).

Данные, которые мы должны сжать, являются одномерным массивом 8-байтовых значений, отсортированных в монотонно увеличивающемся порядке. Значения представляют температуры в Kelvin с промежутком обычно под 100 градусов. Количество значений колеблется от нескольких сотен до в большей части 64K.

Разъяснения

  • Все значения в массиве отличны, хотя повторение действительно существует на уровне байта из-за способа, которым представлены значения с плавающей точкой.

  • Алгоритм без потерь желаем, так как это - научные данные. Преобразование в представление фиксированной точки с достаточной точностью (~5 десятичных чисел) могло бы быть приемлемым, если существует существенное улучшение в эффективности хранения.

Обновление

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

http://users.ices.utexas.edu/~burtscher/papers/dcc06.pdf

20
задан Brian Tompsett - 汤莱恩 17 January 2016 в 19:36
поделиться

5 ответов

size() {
  file="$1"
  if [ -b "$file" ]; then
    /sbin/blockdev --getsize64 "$file"
  else
    wc -c < "$file"  # Handles pseudo files like /proc/cpuinfo
    # stat --format %s "$file"
    # find "$file" -printf '%s\n'
    # du -b "$file" | cut -f1
  fi
}

fs=$(size testing.txt)
-121--3787340-

Это не является обязанностью контроллера, это нарушает SRP . Контроллер вообще не должен знать об UoW. В Web обычно используется один UoW на запрос к серверу. В этом случае UoW должно быть размещено в конце запроса и запущено где-то после начала запроса (в идеале начало UoW должно быть лениво). Лучше всего это делать в Global.asax (или в вашем классе, использующем Application_EndRequest и обработчики Application_BeginRequest.
Этого можно легко достичь с помощью рамок МОК (мой любимый - Виндзор), подробности реализации см. в этом вопросе .

-121--3823462-

Алгоритмы сжатия работают на повторяемости и закономерности, и при этом числа с плавающей запятой плохо работают.

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

Если нет, можете ли вы фильтровать свои температуры, округляя их до эквивалента N цифр (более вероятно, N/.301 бит)? Это может привнести достаточно закономерностей, чтобы быть полезным.

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

1
ответ дан 30 November 2019 в 01:30
поделиться

Можно ли сделать дельту между соседними значениями?
есть ли предел того, насколько значение может изменяться между измерениями? Приемлемо ли ограничить это изменение некоторым максимальным значением скорости (за счет введения некоторого сглаживания?)

Очевидно, существует предел реальной точности значений с термодатчика, нужно ли вам хранить 64 бита точности или Вам лучше хранить целое число, скажем, 0,01-градус Кельвина?

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

РЕДАКТИРОВАТЬ:
Взгляните на типичный набор данных и посмотрите на диапазон различий между соседними значениями. Затем посмотрите, какая точность вам нужна, чтобы это представить.

например. Если у вас есть разница между показаниями не более 1 градуса, вы можете сохранить изменения в 1/256 от этого значения в байте. Если вам нужно сохранить больший диапазон или большую точность, используйте краткое деление на некоторый коэффициент.
Таким образом, следующее чтение будет = last_reading + (float) increment / 256.0

1
ответ дан 30 November 2019 в 01:30
поделиться

Вы можете подумать о перекодировании данных с помощью энтропийного кодера (Хаффмана, Шеннона-Фано, арифметического кодирования). Но это даст хорошие результаты, только если у вас много повторений точек данных и если вы знаете, какие символы будут появляться с той или иной вероятностью.

0
ответ дан 30 November 2019 в 01:30
поделиться

Первое, что следует учесть: попробуйте сжать данные , прежде чем преобразовать их в двойную точность. Повторите свой комментарий Дэвиду Торнли, если ваш АЦП формирования изображения ИК не имеет 24 значащих бита, 32-битные числа с плавающей точкой должны иметь более чем достаточную точность; проблема заключается только в том, чтобы точно сохранить шум, создаваемый последующей обработкой. В противном случае, вероятно, было бы целесообразно реконструировать вашу обработку, определив таблицу значений, которую она генерирует, и вместо этого сохранить индекс для этой таблицы.

Во-вторых: если ваш алгоритм сжатия знает, что ваши данные состоят из 8-байтовых блоков, он будет намного эффективнее; это потому, что он не будет добавлять самые важные байты вместе с младшими байтами. В качестве грубого метода предварительной обработки вы можете попробовать поставить перед каждым двойником префикс отличительного байта (запятая ASCII, возможно?), Прежде чем пропустить его через компрессор на основе байтов, такой как gzip; это должно привести к лучшему общему сжатию, даже если промежуточный поток на 12% больше. Менее грубым, но более трудоемким было бы написать собственное сжатие, адаптированное к этой задаче - возможно, с использованием 8-уровневого дерева для представления ожидаемых значений каждого байта в вашем двойнике.

В-третьих: поскольку данные изображения сильно избыточны, некоторая форма дельта-кодирования или другое сжатие, связанное с изображением, должно сэкономить место. Однако это не принесет вам ужасно большой выгоды, если вы потребуете сжатие без потерь, поскольку шум изображения по своей природе несжимаем. Кроме того, это не поможет вам справиться с псевдослучайным хешем в менее значимых битах ваших двойников, как описано выше.

5
ответ дан 30 November 2019 в 01:30
поделиться

Все перечисленные вами кодировщики ориентированы на байты, и на них влияют некоторые свойства двойников. С одной стороны, есть макет, в котором 12-битная экспонента / знак не очень хорошо сочетается с границами байтов, с другой - шумность вашего ввода. С первой частью легко справиться множеством способов, вторая ограничивает эффективность любого сжатия без потерь, которое вы на нее накладываете. Я думаю, что даже лучший результат будет менее чем потрясающим, я не знаю ваших данных, но подозреваю, что вы можете рассчитывать на экономию всего лишь 25%, более или менее.

Наверное, бесполезно, потому что вы обдумали все, что есть в этом списке ...

  1. Рассматривайте поток как 64-битные целые числа и выполняйте дельта-кодирование смежных значений. Если у вас есть серии значений с одинаковым показателем степени, он будет эффективно обнулять его, а также, возможно, некоторые высокие биты мантиссы. Будут переполнения, но для данных по-прежнему нужно только 64 бита, и операцию можно будет повторить.

  2. На этом этапе вы можете при желании попробовать какое-нибудь грубое целочисленное предсказание и сохранить различия.

  3. Если вы следовали предложению ранее, у вас будет почти половина значений, начиная с 000 ... и почти половина с FFF ... Чтобы устранить это, поверните значение влево (ROL) на 1 бит и выполните XOR. со всеми F, если текущий LSB равен 1. Обратное - это XOR с F, если LSB равен 0, то ROR.

Во-вторых, простая операция XOR для предсказаний истинных значений может быть лучше, чем разница, потому что тогда вам не нужно делать шаг 3.

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

  2. Выполнить общий компрессор или даже сначала RLE с запуском нулей, затем энтропийный энкодер, такой как Huffman, или лучше, энкодер диапазона из 7zip / LZMA.

У ваших данных есть одно преимущество: они однообразны. Есть плохая вещь в ваших данных: это слишком маленький набор. Сколько вы хотите сэкономить, всего килобайты? зачем? Эффективность сжатия сильно пострадает, если между соседними значениями часто есть разница в показателе степени.

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

3
ответ дан 30 November 2019 в 01:30
поделиться
Другие вопросы по тегам:

Похожие вопросы: