Основная идея с арифметическим сжатием - это возможность кодирования вероятности вероятности с использованием точного объема требуемой длины данных.
Это количество данных, как известно, доказано Шеннона, и могут быть вычислены просто используя следующую формулу: -log2 (р)
Например, если р = 50%, то вам необходимо 1 бит. И если p = 25%, вам нужно 2 бита.
Это достаточно просто для вероятностей, которые имеют мощность 2 (и в этом специальном случае достаточно кодирования хаффмана). Но что, если вероятность составляет 63%? Тогда вам понадобится -log2 (0,63) = 0,67 бит. Звучит сложно ...
Это свойство особенно важно, если ваша вероятность высока. Если вы можете предсказать что-то с точностью 95%, тогда вам нужно всего лишь 0,074 бит, чтобы представить хорошее предположение. Это означает, что вы собираетесь сжимать много.
Теперь, как это сделать?
Ну, это проще, чем кажется. Вы будете делить свой диапазон в зависимости от вероятностей. Например, если у вас есть диапазон из 100, 2 возможных события и вероятность 95% для 1-го, тогда первые 95 значений скажут «Событие 1», а последние 5 оставшихся значений скажут «Событие 2», ,
ОК, но на компьютерах мы привыкли использовать мощность 2. Например, с 16 битами у вас есть диапазон 65536 возможных значений. Просто сделайте то же самое: возьмите 1-й 95% диапазона (это 62259), чтобы сказать «Событие 1», а остальное - «Событие 2». У вас, очевидно, проблема «округления» (точность), но до тех пор, пока у вас достаточно значений для распространения, это не имеет большого значения. Кроме того, вы не ограничены двумя событиями, у вас может быть множество событий. Все, что имеет значение, - это то, что значения распределяются в зависимости от вероятностей каждого события.
ОК, но теперь у меня есть 62259 возможных значений, чтобы сказать «Событие 1» и 3277 сказать «Событие 2». Какой из них выбрать? Ну, любой из них будет делать. Wether это 1, 30, 5500 или 62256, это все равно означает «Событие 1».
Фактически, решение о том, какое значение выбрать, не будет зависеть от текущего предположения, а от следующих.
Предположим, у меня есть «Событие 1». Так что теперь я должен выбрать любое значение между 0 и 62256. На следующее предположение, у меня есть тот же дистрибутив (95% Event 1, 5% Event 2). Я просто распределю карту распределения с этими вероятностями. За исключением того, что на этот раз он распределяется по 62256 значениям. И мы продолжаем так, уменьшая диапазон значений с каждой догадкой.
Итак, мы определяем «диапазоны», которые сужаются с каждой догадкой. Однако в какой-то момент есть проблема точности, потому что осталось очень мало значений.
Идея состоит в том, чтобы просто «раздуть» диапазон. Например, каждый раз, когда диапазон опускается ниже 32768 (2^15), вы выводите самый старший бит и умножаете остальные на 2 (эффективно смещая значения на один бит слева). Постоянно делая это, вы выставляете биты один за другим, поскольку они решаются рядом догадок.
Теперь соотношение с сжатием становится очевидным: когда диапазон сужается быстро (например: 5%), вы выводите много бит, чтобы получить диапазон выше предела. С другой стороны, когда вероятность очень велика, диапазон очень медленный. У вас даже может быть много догадок, прежде чем вывести свои первые бит. Вот как можно сжать событие до «доли бит».
Я намеренно использовал термины «вероятность», «догадка», «события», чтобы эта статья была общей. Но для сжатия данных вы просто заменяете их так, как хотите моделировать свои данные. Например, следующим событием может быть следующий байт; в этом случае у вас 256 из них.
Теперь я понимаю вопрос. –
Вы можете найти очень подробное объяснение арифметической кодировки, а также алгоритмы [в этой статье Артуро Сан Эмтерио Кампос] (http://www.arturocampos.com/ac_arithmetic.html). Также вы можете увидеть реализацию C++ для этих алгоритмов в [this post] (http://stackoverflow.com/a/10017164/1009831). –