Арифметическое кодирование — различия между версиями

Материал из Викиконспекты
Перейти к: навигация, поиск
Строка 40: Строка 40:
 
Рассмотрим в качестве примера строку <tex>abacaba</tex>
 
Рассмотрим в качестве примера строку <tex>abacaba</tex>
 
=== Кодирование ===
 
=== Кодирование ===
 +
[[Файл:Code_png.png|thumb|right|400px|Пример работы кодировщика ]]
 
{|class="wikitable"
 
{|class="wikitable"
 
!Символ||Частота появления
 
!Символ||Частота появления
Строка 69: Строка 70:
 
|}
 
|}
 
Код: <tex>0.411471</tex>
 
Код: <tex>0.411471</tex>
 +
 
=== Декодирование ===
 
=== Декодирование ===

Версия 00:32, 24 декабря 2011

Определение

Определение:
Арифметическое кодирование (Arithmetic coding) — алгоритм сжатия информации без потерь.

Данный метод (как и алгоритм Хаффмана) является энтропийным т.е. длина кода конкретного символа зависит от частоты встречаемости этого символа в тексте. Арифметическое кодирование показывает более высокие результаты сжатия, чем алгоритм Хаффмана, для данных с неравномерными распределениями вероятностей кодируемых символов. Кроме того, при арифметическом кодировании каждый символ кодируется нецелым числом бит, что эффективнее кода Хаффмана (теоретически символу [math]a[/math] с вероятностью появления [math]p(a)[/math] допустимо ставить в соответствие код длины [math]-log_2(p(a))[/math], следовательно при кодировании Хаффманом это достигается только с вероятностями, равными обратным степеням двойки).

Принцип действия

Кодирование

Алгоритму передаются текст для кодирования и список частот встречаемости символов.

  1. Рассмотрим отрезок [math][0; 1)[/math] на координатной прямой.
  2. Поставим каждому символу текста в соответствие отрезок, длина которого равна частоте его появления.
  3. Считаем символ из входного потока и рассмотрим отрезок, соответствующий этому символу. Этот отрезок разделим на части, пропорциональные частотам встречаемости символов.
  4. Повторим пункт (3) до конца входного потока.
  5. Выберем любое число из получившегося отрезка (предпочтительно степень двойки). Это и будет результат арифметического кодирования.

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. Выберем на отрезке [math][0; 1)[/math], разделенном на части, длины которых равны вероятностям появления символов в тексте, подотрезок, содержащий входное вещественное число. Символ, соответствующий этому подотрезку, дописываем в ответ.
  2. Нормируем подотрезок и вещественное число.
  3. Повторим п. (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)

Пример работы

Рассмотрим в качестве примера строку [math]abacaba[/math]

Кодирование

Пример работы кодировщика
Символ Частота появления

[math]a[/math]

[math]0.571429[/math]

[math]b[/math]

[math]0.285714[/math]

[math]c[/math]

[math]0.142857[/math]

Считанный символ Левая граница отрезка Правая граница отрезка

[math]0[/math]

[math]1[/math]

[math]a[/math]

[math]0[/math]

[math]0.571429[/math]

[math]b[/math]

[math]0.326531[/math]

[math]0.489796[/math]

[math]a[/math]

[math]0.326531[/math]

[math]0.419825[/math]

[math]c[/math]

[math]0.406497[/math]

[math]0.419825[/math]

[math]a[/math]

[math]0.406497[/math]

[math]0.414113[/math]

[math]b[/math]

[math]0.410849[/math]

[math]0.413025[/math]

[math]a[/math]

[math]0.410849[/math]

[math]0.412093[/math]

Код: [math]0.411471[/math]

Декодирование