Арифметическое кодирование — различия между версиями
Darkraven (обсуждение | вклад) |
|||
Строка 37: | Строка 37: | ||
while (segment[i].character != eof) | while (segment[i].character != eof) | ||
</code> | </code> | ||
+ | == Пример работы == | ||
+ | Рассмотрим в качестве примера строку <tex>abacaba</tex> | ||
+ | === Кодирование === | ||
+ | {|class="wikitable" | ||
+ | !Символ||Частота появления | ||
+ | |- | ||
+ | |<p style="text-align:center;"><tex>a</tex></p>||<p style="text-align:center;"><tex>0.571429</tex></p> | ||
+ | |- | ||
+ | |<p style="text-align:center;"><tex>b</tex></p>||<p style="text-align:center;"><tex>0.285714</tex></p> | ||
+ | |- | ||
+ | |<p style="text-align:center;"><tex>c</tex></p>||<p style="text-align:center;"><tex>0.142857</tex></p> | ||
+ | |} | ||
+ | {|class="wikitable" | ||
+ | !Считанный символ||Левая граница отрезка||Правая граница отрезка | ||
+ | |- | ||
+ | |||<p style="text-align:center;"><tex>0</tex></p>||<p style="text-align:center;"><tex>1</tex></p> | ||
+ | |- | ||
+ | |<p style="text-align:center;"><tex>a</tex></p>||<p style="text-align:center;"><tex>0</tex></p>||<p style="text-align:center;"><tex>0.571429</tex></p> | ||
+ | |- | ||
+ | |<p style="text-align:center;"><tex>b</tex></p>||<p style="text-align:center;"><tex>0.326531</tex></p>||<p style="text-align:center;"><tex>0.489796</tex></p> | ||
+ | |- | ||
+ | |<p style="text-align:center;"><tex>a</tex></p>||<p style="text-align:center;"><tex>0.326531</tex></p>||<p style="text-align:center;"><tex>0.419825</tex></p> | ||
+ | |- | ||
+ | |<p style="text-align:center;"><tex>c</tex></p>||<p style="text-align:center;"><tex>0.406497</tex></p>||<p style="text-align:center;"><tex>0.419825</tex></p> | ||
+ | |- | ||
+ | |<p style="text-align:center;"><tex>a</tex></p>||<p style="text-align:center;"><tex>0.406497</tex></p>||<p style="text-align:center;"><tex>0.414113</tex></p> | ||
+ | |- | ||
+ | |<p style="text-align:center;"><tex>b</tex></p>||<p style="text-align:center;"><tex>0.410849</tex></p>||<p style="text-align:center;"><tex>0.413025</tex></p> | ||
+ | |- | ||
+ | |<p style="text-align:center;"><tex>a</tex></p>||<p style="text-align:center;"><tex>0.410849</tex></p>||<p style="text-align:center;"><tex>0.412093</tex></p> | ||
+ | |} | ||
+ | Код: <tex>0.411471</tex> | ||
+ | === Декодирование === |
Версия 00:12, 24 декабря 2011
Содержание
Определение
Определение: |
Арифметическое кодирование (Arithmetic coding) — алгоритм сжатия информации без потерь. |
Данный метод (как и алгоритм Хаффмана) является энтропийным т.е. длина кода конкретного символа зависит от частоты встречаемости этого символа в тексте. Арифметическое кодирование показывает более высокие результаты сжатия, чем алгоритм Хаффмана, для данных с неравномерными распределениями вероятностей кодируемых символов. Кроме того, при арифметическом кодировании каждый символ кодируется нецелым числом бит, что эффективнее кода Хаффмана (теоретически символу
с вероятностью появления допустимо ставить в соответствие код длины , следовательно при кодировании Хаффманом это достигается только с вероятностями, равными обратным степеням двойки).Принцип действия
Кодирование
Алгоритму передаются текст для кодирования и список частот встречаемости символов.
- Рассмотрим отрезок на координатной прямой.
- Поставим каждому символу текста в соответствие отрезок, длина которого равна частоте его появления.
- Считаем символ из входного потока и рассмотрим отрезок, соответствующий этому символу. Этот отрезок разделим на части, пропорциональные частотам встречаемости символов.
- Повторим пункт (3) до конца входного потока.
- Выберем любое число из получившегося отрезка (предпочтительно степень двойки). Это и будет результат арифметического кодирования.
left = 0
right = 1
while !eof
read(symb)
newRight = left + (right - left) * segment[symb].right //segment[symb] — подотрезок отрезка [0; 1), соответствующий символу symb
newLeft = left + (right - left) * segment[symb].left
left = newLeft
right = newRight
ans = (left + right) / 2
Декодирование
Алгоритм по вещественному числу восстанавливает исходный текст.
- Выберем на отрезке , разделенном на части, длины которых равны вероятностям появления символов в тексте, подотрезок, содержащий входное вещественное число. Символ, соответствующий этому подотрезку, дописываем в ответ.
- Нормируем подотрезок и вещественное число.
- Повторим п. (1—2) до тех пор, пока не получим ответ (до конца файла).
do for i = 1 to n if code >= segment[i].left && code < segment[i].right write(segment[i].character) code = (code – segment[i].left) / (segment[i].right – segment[i].left) break while (segment[i].character != eof)
Пример работы
Рассмотрим в качестве примера строку
Кодирование
Символ | Частота появления |
---|---|
| |
| |
|
Считанный символ | Левая граница отрезка | Правая граница отрезка |
---|---|---|
| ||
| ||
| ||
| ||
| ||
| ||
| ||
|
Код: