Арифметическое кодирование — различия между версиями
Migan (обсуждение | вклад) м (Фикс замечаний и источников информации) |
Migan (обсуждение | вклад) (Оформление второго псевдокода в виде функции) |
||
Строка 10: | Строка 10: | ||
# Повторим пункт (3) до конца входного потока. | # Повторим пункт (3) до конца входного потока. | ||
# Выберем любое число из получившегося отрезка, которое и будет результатом арифметического кодирования. | # Выберем любое число из получившегося отрезка, которое и будет результатом арифметического кодирования. | ||
− | '''double''' ArithmeticCoding (s: string): | + | '''double''' ArithmeticCoding (s: '''string'''): |
left = 0 | left = 0 | ||
right = 1 | right = 1 | ||
Строка 25: | Строка 25: | ||
# Выберем на отрезке <tex>[0; 1)</tex>, разделенном на части, длины которых равны вероятностям появления символов в тексте, подотрезок, содержащий входное вещественное число. Символ, соответствующий этому подотрезку, дописываем в ответ. | # Выберем на отрезке <tex>[0; 1)</tex>, разделенном на части, длины которых равны вероятностям появления символов в тексте, подотрезок, содержащий входное вещественное число. Символ, соответствующий этому подотрезку, дописываем в ответ. | ||
# Нормируем подотрезок и вещественное число. | # Нормируем подотрезок и вещественное число. | ||
− | # Повторим пункты 1{{---}}2 до тех пор, пока не получим ответ | + | # Повторим пункты 1{{---}}2 до тех пор, пока не получим ответ. |
<code> | <code> | ||
− | ''' | + | '''string''' ArithmeticCoding (code: '''double'''): |
− | + | s = "" | |
− | + | '''for''' i = 1 to length | |
− | + | '''for''' j = 1 '''to''' n | |
− | + | '''if''' code >= segment[j].left '''and''' code < segment[j].right | |
− | + | s = s + segment[j].character | |
− | + | code = (code – segment[j].left) / (segment[j].right – segment[j].left) | |
+ | '''break''' | ||
+ | '''return''' s | ||
</code> | </code> | ||
Версия 15:44, 17 июня 2016
Арифметическое кодирование (англ. Arithmetic coding) — алгоритм сжатия информации без потерь, который при кодировании ставит в соответствие тексту вещественное число из отрезка алгоритм Хаффмана, является энтропийным, т.е. длина кода конкретного символа зависит от частоты встречаемости этого символа в тексте. Арифметическое кодирование показывает более высокие результаты сжатия, чем алгоритм Хаффмана, для данных с неравномерными распределениями вероятностей кодируемых символов. Кроме того, при арифметическом кодировании каждый символ кодируется нецелым числом бит, что эффективнее кода Хаффмана (теоретически, символу с вероятностью появления допустимо ставить в соответствие код длины , следовательно, при кодировании алгоритмом Хаффмана это достигается только с вероятностями, равными обратным степеням двойки).
. Данный метод, как иСодержание
Принцип действия
Кодирование
На вход алгоритму передаются текст для кодирования и список частот встречаемости символов.
- Рассмотрим отрезок на координатной прямой.
- Поставим каждому символу текста в соответствие отрезок, длина которого равна частоте его появления.
- Считаем символ из входного потока и рассмотрим отрезок, соответствующий этому символу. Разделим этот отрезок на части, пропорциональные частотам встречаемости символов.
- Повторим пункт (3) до конца входного потока.
- Выберем любое число из получившегося отрезка, которое и будет результатом арифметического кодирования.
double ArithmeticCoding (s: string):
left = 0
right = 1
for i = 0 to length(s)-1
read(s[i])
newRight = left + (right - left) * segment[symb].right // segment[symb] — подотрезок отрезка [0; 1), соответствующий символу symb
newLeft = left + (right - left) * segment[symb].left
left = newLeft
right = newRight
return (left + right) / 2
Декодирование
Алгоритм по вещественному числу восстанавливает исходный текст.
- Выберем на отрезке , разделенном на части, длины которых равны вероятностям появления символов в тексте, подотрезок, содержащий входное вещественное число. Символ, соответствующий этому подотрезку, дописываем в ответ.
- Нормируем подотрезок и вещественное число.
- Повторим пункты 1—2 до тех пор, пока не получим ответ.
string ArithmeticCoding (code: double): s = "" for i = 1 to length for j = 1 to n if code >= segment[j].left and code < segment[j].right s = s + segment[j].character code = (code – segment[j].left) / (segment[j].right – segment[j].left) break return s
Замечание: кодировщику и декодировщику должно быть известно, когда завершать работу. Для этого можно передавать в качестве аргумента длину текста или символ конца файла, после которого процесс должен быть остановлен.
Для оптимизации размера кода необходимо выбрать из окончательного диапазона число, содержащее наименьшее количество знаков в двоичной записи.
Пример работы
Рассмотрим в качестве примера строку
Кодирование
Символ | Частота появления |
---|---|
| |
| |
|
Считанный символ | Левая граница отрезка | Правая граница отрезка |
---|---|---|
| ||
| ||
| ||
| ||
| ||
| ||
| ||
|
Код:
Декодирование
Код:
Декодируемый символ | Код |
---|---|
| |
| |
| |
| |
| |
| |
|
Замечание: при декодировании текста можно не только нормализовывать рабочий отрезок и текущий код, но и уменьшать рабочий отрезок (аналогично кодированию), не изменяя значение кода.
Декодирование (второй способ)
Код:
Декодируемый символ | Границы отрезка | |||
---|---|---|---|---|
| ||||
| ||||
| ||||
| ||||
| ||||
| ||||
|
Оценка длины кодового слова
Теорема: |
При арифметическом кодировании длина кодового слова не превышает энтропии исходного текста. |
Доказательство: |
Размер сообщения Число бит в закодированном тексте: ( — длина текста; — размер алфавита; — частота встречаемости символа; — вероятность вхождения символа) |