Этот вопрос о том, сколько бит требуется для хранения диапазона. Или, другими словами, для данного числа битов, какой максимальный диапазон может быть сохранен и как?
Представьте, что мы хотим сохранить поддиапазон в диапазоне 0-255.
Так например 45-74.
Мы можем сохранить приведенный выше пример в виде двух неподписанных байтов, но мне кажется, что там должна быть некоторая избыточность информации. Мы знаем, что второе значение больше первого, поэтому в случае, когда первое значение велико, для второго значения требуется меньше битов, а в случае, когда второе значение велико, для первого требуется меньше битов. ,
Я подозреваю, что любой метод сжатия дал бы предельный результат, поэтому лучше задать вопрос: «Каков максимальный диапазон, который может быть сохранен в одном байте?». Это должно быть больше, чем то, что достижимо, если хранить два числа отдельно.
Существуют ли стандартные алгоритмы для такого рода вещей?
Ответы:
Просто посчитайте количество возможных диапазонов. Есть 256 диапазонов с нижней границей 0 (0-0, 0-1, ... 0-254, 0-255), 255 диапазонов с нижней границей 1, ... и, наконец, 1 диапазон с нижней границей 255 (255- 255). Таким образом, общее число (256 + 255 + ... + 1) = 257 * 128 = 32 896. Поскольку это немного больше, чем 2 15 = 32 768, вам все равно понадобится как минимум 16 бит (2 байта) для хранения этой информации.
Как правило, для чисел от 0 до n-1 число возможных диапазонов равно n * (n + 1) / 2. Это меньше 256, если n равно 22 или меньше: n = 22 дает 22 * 23/2 = 253 возможностей. Таким образом, одного байта достаточно для поддиапазонов 0-21 .
Другой способ взглянуть на проблему заключается в следующем: сохранение пары целых чисел в диапазоне от 0 до n-1 - почти то же самое, что хранение поддиапазона 0- (n-1) плюс один бит, который определяет, является ли первое число ниже или выше второго. (Разница возникает в том случае, когда оба целых числа равны, но этот шанс становится все меньше по мере того, как n увеличивается.) Вот почему вы можете сэкономить только один бит с помощью этого метода, и, вероятно, это основная причина, почему он используется редко.
источник
n * (n + 1) / 2 + 1
! Крошечная перемена.Для такого небольшого количества бит невозможно сохранить много бит, как указывал Глорфиндель . Однако, если используемый вами домен имеет еще несколько битов, вы можете добиться значительной экономии для среднего случая, кодируя диапазоны с начальным значением и дельтой.
Предположим, что домен - это целые числа, поэтому 32 бита. При наивном подходе вам нужно 64 бита (начало, конец) для хранения диапазона.
Если мы переключимся на кодировку (start, delta), мы можем построить конец диапазона из этого. Мы знаем, что в худшем случае начало равно 0, а дельта имеет 32 бита.
2 ^ 5 равно 32, поэтому мы кодируем длину дельты в пять битов (без нулевой длины, всегда добавляем 1), и кодирование становится (начало, длина, дельта). В худшем случае это стоит 32 * 2 + 5 бит, то есть 69 бит. Таким образом, в худшем случае, если все диапазоны длинные, это хуже, чем простое кодирование.
В лучшем случае это стоит 32 + 5 + 1 = 38 бит.
Это означает, что если вам нужно закодировать много диапазонов, и каждый из этих диапазонов охватывает только небольшую часть вашего домена, вы в конечном итоге будете использовать меньше места в среднем, используя эту кодировку. Неважно, как распределяются старты, поскольку старт всегда будет занимать 32 бита, но важно, как распределяются длины диапазонов. Если чем меньше длина, тем лучше сжатие, чем больше диапазонов, охватывающих всю длину домена, тем хуже будет эта кодировка.
Однако, если у вас много диапазонов, сгруппированных вокруг одинаковых начальных точек (например, потому что вы получаете значения от датчика), вы можете добиться еще большей экономии. Вы можете применить ту же технику к начальному значению и использовать смещение, чтобы сместить начальное значение.
Допустим, у вас есть 10000 диапазонов. Диапазоны сгруппированы вокруг определенного значения. Вы кодируете смещение с 32 битами.
Используя наивный подход, вам потребуется 32 * 2 * 10 000 = 640 000 бит для хранения всех этих диапазонов.
Кодирование смещения занимает 32 бита, а в лучшем случае кодирование каждого диапазона занимает 5 + 1 + 5 + 1 = 12 бит, что в сумме составляет 120 000 + 32 = 120 032 бита. В худшем случае вам нужно 5 + 32 + 5 + 32 бита, то есть 74 бита, всего 740 032 бита.
Это означает, что для 10 000 значений в домене, для кодирования которого требуется 32 бита, мы получаем
Если вы берете простое кодирование в качестве базового уровня, это означает либо экономию до 81,25%, либо до 15,625% больше затрат.
В зависимости от того, как распределяются ваши ценности, эта экономия значительна. Знай свой бизнес домен! Знайте, что вы хотите закодировать.
В качестве расширения вы также можете изменить смещение. Если вы анализируете данные и идентифицируете группы значений, вы можете сортировать данные в сегменты и кодировать каждый из этих сегментов отдельно, с собственным смещением. Это означает, что вы можете применить эту технику не только к диапазонам, которые сгруппированы вокруг одного начального значения, но также и к диапазонам, которые сгруппированы вокруг нескольких значений.
Если ваши начальные точки распределены одинаково, эта кодировка не очень хорошо работает.
Эта кодировка явно плохо подходит для индексации. Вы не можете просто прочитать х-е значение. Он может быть прочитан только последовательно. Что подходит в некоторых ситуациях, например, для потоковой передачи по сети или хранилищу данных (например, на ленте или на жестком диске).
Оценка данных, их группировка и выбор правильного смещения могут быть существенной работой и могут потребовать некоторой корректировки для достижения оптимальных результатов.
источник
Проблема такого рода - предмет оригинальной статьи Клода Шеннона « Математическая теория коммуникации» , в которой введено слово «бит» и более или менее изобретенное сжатие данных.
Общая идея заключается в том, что количество битов, используемых для кодирования диапазона, обратно пропорционально вероятности возникновения этого диапазона. Например, предположим, что диапазон 45-74 появляется примерно в 1/4 времени. Вы можете сказать, что последовательность 00 соответствует 45-74. Чтобы кодировать диапазон 45-74, вы выводите «00» и останавливаетесь на этом.
Давайте также предположим, что диапазоны 99-100 и 140-155 каждый появляются примерно в 1/8 времени. Вы можете кодировать каждый из них 3-битной последовательностью. Любые 3 бита будут работать до тех пор, пока они не начнутся с «00», который уже зарезервирован для диапазона 45–74.
Вы можете продолжать таким образом, пока каждый возможный диапазон не будет иметь кодировку. Для наименее вероятного диапазона может потребоваться более 100 бит. Но это нормально, потому что это редко появляется.
Там являются алгоритмы для поиска оптимального кодирования. Я не буду пытаться объяснить их здесь, но вы можете узнать больше, перейдя по ссылке выше или в поисках «Теория информации», «Кодирование Шеннона-Фано» или «Кодирование Хаффмана».
Как уже отмечали другие, вероятно, лучше хранить начальный номер и разницу между начальным и конечным номером. Вы должны использовать одну кодировку для начала, а другую для разницы, так как они имеют разные распределения вероятностей (и я предполагаю, что последняя более избыточна). Как предложил Polygnome, лучший алгоритм зависит от вашего домена.
источник
Чтобы расширить ответ от @Glorfindel:
При n → ∞, (n - 1) → n. Таким образом, Ω (диапазоны) → n² / 2 и log (Ω (диапазоны)) → (2n - 1). Поскольку простое кодирование занимает 2n битов, асимптотическое максимальное сжатие сохраняет только 1 бит.
источник
Есть аналогичный ответ, но для достижения оптимального сжатия вам необходимо:
Важно отметить, что число 2 означает, что вы хотите кодировать вещи таким образом, чтобы наиболее информативные значения (для каждого закодированного бита) были первыми. Например, хотя я предложил кодировать отсортированный список «как есть», обычно разумнее было бы кодировать его как «двоичное дерево», т. Е. Если они отсортированы по ширине, а у вас есть
len
элементы, начните с элемента кодированияlen/2
, Скажем, у него была ширина w. Теперь вы знаете, что все элементы имеют ширину где-то в [0, w], и все элементы имеют ширину где-то в [w, max val, который вы принимаете] Повторяйте рекурсивно (снова подразделяя каждую половину списка пополам и т. Д.) До тех пор, пока вы не закроетеlen
элементы (если это не исправлено, вы захотите закодироватьlen
во-первых, вам не нужно беспокоиться об окончании токенов). Если «max val you accept» действительно открыт, может быть целесообразно сначала закодировать самое высокое значение, которое фактически появляется в ваших данных, то есть последний элемент, а затем выполнить двоичное разбиение. Опять же, все, что является наиболее информативным в первую очередь.Кроме того, если вы сначала кодируете ширину интервала и знаете максимально возможное значение, с которым вы имеете дело, очевидно, вы можете исключить все начальные значения, которые могут привести к его переполнению ... вы поняли идею. Преобразовывайте и упорядочивайте свои данные таким образом, чтобы вы могли вывести как можно больше информации об остальных данных при их декодировании, а оптимальный алгоритм энтропийного кодирования позволит вам не тратить впустую информацию о кодировании битов, которую вы «уже знаете» ,
источник