577
правок
Изменения
→Универсальное кодирование
Простейшими кодами, на основе которых может выполняться сжатие данных, являются '''коды без памяти''' (англ. ''code without memory''). В коде без памяти каждый символ в кодируемом векторе данных заменяется кодовым словом из префиксного множества двоичных последовательностей или слов.
== Разделение мантисс и экспонент ==
Основная идея состоит в том, чтобы отдельно описывать порядок значения элемента ("экспоненту" <tex>E_i</tex>) и отдельно {{---}} значащие цифры значения ("мантиссу" <tex>M_i</tex>).
Значащие цифры начинаются со старшей ненулевой цифры: например, в числе <tex>000001101_2</tex> = <tex>1\times2^0+0\times2^1+1\times2^2+1\times2^3+0\times2^4+0\times... \dots = 13</tex> это последние <tex>4</tex> цифры. Порядок числа определяется позицией старшей ненулевой цифры в записи числа. Как и при обычной записи в десятичной системе, он равен числу цифр в записи числа без предшествующих незначащих нулей. В данном примере порядок равен четырем.
Методы данной группы являются трансформирующими и поточными, то есть могут применяться даже в том случае, когда объем входных данных заранее не известен. В общем случае скорость работы компрессора (содержащего прямое, "сжимающее" преобразование) равна скорости декомпрессора (реализующего обратное, "разжимающее" преобразование) и зависит только от объема исходных данных. Памяти потребуется всего несколько байт.
|definition ='''Унарное представление числа <tex>n</tex> ''' (англ. ''unary code'') {{---}} <tex>n</tex> подряд идущих единиц, заканчивающихся контрольным нулем (иногда наоборот: <tex>n</tex> нулей, за которыми следует контрольная единица). Более наглядно унарные коды можно представить в виде двоичного дерева, которое устроено следующим образом: каждому ребру, ведущему из вершины к правому ребенку, соответствует единица, иначе ноль, причем левый ребенок уже не имеет детей. Например, если нужно закодировать число m, нужно m раз пройти по правым вершинам и затем остановиться на левой.}}
Например, унарный код нуля {{---}} <tex>0</tex>, единицы {{---}} <tex>10</tex>, двойки {{---}} <tex>110</tex> и т. д.
=== Гамма-код Элиаса ===
# Считываем нули до первой единицы, <tex>N = 3</tex>.
# Считываем единицу и <tex>N = 3</tex> бит. Получаем <tex>2^3</tex> + <tex>111_2+</tex> = '''<tex>111_2 = 15</tex>'''.
Приведем примеры нескольких первых гамма-кодов Элиаса:
|}
Гамма-код Элиаса не подходит для кодирования нулевых значений или отрицательных чисел. Для того, чтобы закодировать ноль нужно прибавить к нему <tex>1</tex> до кодирования и отнять после декодирования. Чтобы закодировать все целые числа можно установить биекцию (соответствие), отображая целые числа из <tex>(0, 1, -1, 2, -2, 3, -3, ...\dots)</tex> в <tex>(1, 2, 3, 4, 5, 6, 7, ...\dots)</tex>.
=== Дельта-код Элиаса ===
'''Пример кодирования числа <tex>10</tex>'''
# В двоичном представлении числа <tex>N = 10 = 1010_2 </tex> всего <tex>4</tex> значащих бита <tex>(L = 4)</tex>.# В двоичном представлении числа <tex>L = 4 = 100_2 </tex> всего <tex>3</tex> значащих бита <tex>(M = 3)</tex>.
# Пишем <tex>M</tex> {{---}} <tex>1</tex> ноль и одну единицу <tex>001</tex>.
# Дописываем справа биты числа <tex>L</tex> без старшей единицы <tex>00100</tex>.
! Диапазон || Гамма-коды || Длина кода, бит || Дельта-коды || Длина кода, бит
|-align="center" bgcolor=#FFFFFF
|1||'''1'''|||1||'''1'''||1
|-align="center" bgcolor=#FFFFFF
|2...3||'''01x'''||3||'''010x'''||4
|-align="center" bgcolor=#FFFFFF
|4...7||'''001xx'''||5||'''011xx'''||5
|-align="center" bgcolor=#FFFFFF
|8...15||'''0001xxx'''||7||'''00100xxx'''||8
|-align="center" bgcolor=#FFFFFF
|16...31||'''00001xxxx'''||9||'''00101xxxx'''||9
|-align="center" bgcolor=#FFFFFF
|32...63||'''000001xxxxx'''||11||'''00110xxxxx'''||10
|-align="center" bgcolor=#FFFFFF
|64...127||'''0000001xxxxxx'''||13||'''00111xxxxxx'''||11
|-align="center" bgcolor=#FFFFFF
|128...255||'''00000001xxxxxxx'''||15||'''0001000xxxxxxx'''||14
|}
и т. д. Символами "x" тут обозначены биты мантиссы без старшей единицы.
'''Гамма-код''': <tex>00..(K</tex> раз<tex>)..01x..(K</tex> раз<tex>)..x</tex>; длина <tex>2\times{K} + 1</tex> бит;
'''Дельта-код''': <tex>n...(2\times{L}+1</tex> раз<tex>)...nx..(K</tex> раз<tex>)..x</tex>; длина: <tex>2\times{L}+K+1</tex> бит, где <tex>L = [\log_2{(K+1)}]</tex> {{- --}} целая часть логарифма числа <tex>(K+1)</tex> по основанию <tex>2</tex>; <tex>n</tex> {{--- }} биты, относящиеся к записи экспоненты дельта-кода, их число <tex>2\times{L} + 1</tex>.
Единственное отличие между гамма- и дельта-кодами состоит в том, что в гамма-кодах экспоненты записываются в унарном виде, а в дельта-кодах к ним еще раз применяется гамма-кодирование.
Можно видеть, что для чисел <tex>2, 3, 8...\dots 15</tex> дельта-код длиннее гамма-кода, для чисел <tex>1, 4...7, 16...31</tex> длина дельта-кода совпадает с длиной гамма-кода, для всех остальных чисел дельта-код короче гамма-кода. Это происходит вследствие того, как строятся данные коды. Как показано выше, длина гама-кода <tex>2\times{K} + 1</tex>, что при больших <tex>K</tex> очевидно больше, чем <tex>2\times{[\log_2{(K+1)}]} + K + 1</tex>
=== Омега-код Элиаса ===
{{Определение
|id = def1
|definition ='''Омега-код Элиаса ''' (англ. ''Elias omega code'') {{---}} — это универсальный код для кодирования положительных целых чисел, разработанный Питером Элиасом. Так же, как гамма- и дельта-код Элиаса, он приписывает к началу целого числа порядок его величины в универсальном коде. Однако, в отличие от двух других указанных кодов, омега-код рекурсивно кодирует префикс, именно поэтому он также известен, как '''рекурсивный код Элиаса'''.}}
Омега-кодирование используется в приложениях, где самое большое кодируемое значение неизвестно заранее, или для сжатия данных, в которых маленькие значения встречаются намного чаще, чем большие.
Данные коды состоят из последовательности групп длинной <tex>L_1, L_2, L_3, …\dots, L_m</tex> бит, которые начинаются (слева) с бита <tex>1</tex>. В конце последовательности (справа) всегда <tex>0</tex>. Длина каждой следующей <tex>(n+1)</tex>-й группы задается значением битов предыдущей <tex>n</tex>-й группы.
В омега-кодах Элиаса длина первой группы {{---}} <tex>2</tex> бита. Длина следующей группы на единицу больше значения предыдущей. Первое значение задается отдельно.
# В конец представления записать <tex>0</tex>.
# Если число не единица <tex>({N}\neq1)</tex>, слева от построенной последовательности добавить его двоичное представление.
# В <tex>N</tex> записать новое значение {{- --}} количество только что записанных цифр(бит), минус один.
# Вернуться к шагу 2.
# <tex>16 ... 65536 (2^{2^2} ... 2^{2^{2^2}} - 1)</tex> {{---}} <tex>3</tex> группы;
# <tex>65536 ... 2\times10^{19728} (2^{2^{2^2}} ... 2^{2^{2^{2^2}}} - 1)</tex> {{---}} всего <tex>4</tex> группы.
Здесь быстрое возрастание количества значений в группе сильно напоминает [[СНМ (реализация с помощью леса корневых деревьев)#Асимптотика|функцию Аккермана]]. Начиная с третьей <tex>(i = 3)</tex> группы их диапазон лежит между значениями функции <tex>A(i - 3, 4) + 3</tex> и <tex>A(i -2, 4) + 3</tex>.
{| class="wikitable" style="width:10cm" border=1
*Д. Ватолин, Ратушняк, М. Смирнов, В. Юкин "Методы сжатия данных"
*[http://rain.ifmo.ru/cat/view.php/theory/coding/integer-2005 Кодирование целых чисел]
*[https://ru.wikipedia.org/wiki/%D0%93%D0%B0%D0%BC%D0%BC%D0%B0-%D0%BA%D0%BE%D0%B4_%D0%AD%D0%BB%D0%B8%D0%B0%D1%81%D0%B0 Википедия {{- --}} Гамма-код Элиаса]*[https://ru.wikipedia.org/wiki/%D0%94%D0%B5%D0%BB%D1%8C%D1%82%D0%B0-%D0%BA%D0%BE%D0%B4_%D0%AD%D0%BB%D0%B8%D0%B0%D1%81%D0%B0 Википедия {{--- }} Дельта-код Элиаса]*[https://ru.wikipedia.org/wiki/%D0%9E%D0%BC%D0%B5%D0%B3%D0%B0-%D0%BA%D0%BE%D0%B4_%D0%AD%D0%BB%D0%B8%D0%B0%D1%81%D0%B0 Википедия {{--- }} Омега-код Элиаса]*[https://ru.wikipedia.org/wiki/%D0%A3%D0%BD%D0%B8%D0%B2%D0%B5%D1%80%D1%81%D0%B0%D0%BB%D1%8C%D0%BD%D1%8B%D0%B9_%D0%BA%D0%BE%D0%B4 Википедия {{--- }} Универсальный код]
[[Категория: Дискретная математика и алгоритмы]]
[[Категория: Алгоритмы сжатия ]]