Гамма-код Элиаса: различия между версиями
w>TXiKiBoT м (робот добавил: fr:Codage gamma) |
In.wiki (комментарии | вклад) м (45 версий импортировано: Импорт из Википедии) |
||
(не показано 26 промежуточных версий 18 участников) | |||
Строка 4: | Строка 4: | ||
Чтобы закодировать число: | Чтобы закодировать число: | ||
# Записать его в двоичной форме. | # Записать его в двоичной форме. | ||
− | # Перед двоичным представлением числа дописать нули. Количество | + | # Перед двоичным представлением числа дописать нули. Количество нулей на единицу меньше количества битов двоичного представления числа. |
Аналогичный способ описания этого процесса: | Аналогичный способ описания этого процесса: | ||
− | # | + | # Выделить из целого числа старший значащий бит (самую большую степень 2, которую число включает — 2<sup>N</sup>) и младшие N бит. |
− | # Записать N в унарном коде; то есть N нолей, | + | # Записать N в унарном коде; то есть N нолей, за которыми следует единица. |
− | # | + | # Дописать N младших двоичных цифр числа следом за этим унарным кодом. |
Начало кодирования: | Начало кодирования: | ||
Строка 18: | Строка 18: | ||
| 1 || 2<sup>0</sup> + 0 || 1 || 1/2 | | 1 || 2<sup>0</sup> + 0 || 1 || 1/2 | ||
|- | |- | ||
− | | 2 || 2<sup>1</sup> + 0 || | + | | 2 || 2<sup>1</sup> + 0 || 0 1 0 || 1/8 |
|- | |- | ||
− | | 3 || 2<sup>1</sup> + 1 || | + | | 3 || 2<sup>1</sup> + 1 || 0 1 1 || 1/8 |
|- | |- | ||
− | | 4 || 2² + 0 || | + | | 4 || 2² + 0 || 00 1 00 || 1/32 |
|- | |- | ||
− | | 5 || 2² + 1 || | + | | 5 || 2² + 1 || 00 1 01 || 1/32 |
|- | |- | ||
− | | 6 || 2² + 2 || | + | | 6 || 2² + 2 || 00 1 10 || 1/32 |
|- | |- | ||
− | | 7 || 2² + 3 || | + | | 7 || 2² + 3 || 00 1 11 || 1/32 |
|- | |- | ||
− | | 8 || 2³ + 0 || | + | | 8 || 2³ + 0 || 000 1 000 || 1/128 |
|- | |- | ||
− | | 9 || 2³ + 1 || | + | | 9 || 2³ + 1 || 000 1 001 || 1/128 |
|- | |- | ||
− | |10 || 2³ + 2 || | + | |10 || 2³ + 2 || 000 1 010 || 1/128 |
|- | |- | ||
− | |11 || 2³ + 3 || | + | |11 || 2³ + 3 || 000 1 011 || 1/128 |
|- | |- | ||
− | |12 || 2³ + 4 || | + | |12 || 2³ + 4 || 000 1 100 || 1/128 |
|- | |- | ||
− | |13 || 2³ + 5 || | + | |13 || 2³ + 5 || 000 1 101 || 1/128 |
|- | |- | ||
− | |14 || 2³ + 6 || | + | |14 || 2³ + 6 || 000 1 110 || 1/128 |
|- | |- | ||
− | |15 || 2³ + 7 || | + | |15 || 2³ + 7 || 000 1 111 || 1/128 |
|- | |- | ||
− | |16 || 2<sup>4</sup> + 0 || | + | |16 || 2<sup>4</sup> + 0 || 0000 1 0000 || 1/512 |
|- | |- | ||
− | |17 || 2<sup>4</sup> + 1 || | + | |17 || 2<sup>4</sup> + 1 || 0000 1 0001 || 1/512 |
|- | |- | ||
|… || || || | |… || || || | ||
Строка 58: | Строка 58: | ||
# Считать все нули, встречающиеся до первой 1. Пусть N — количество этих нулей. | # Считать все нули, встречающиеся до первой 1. Пусть N — количество этих нулей. | ||
− | # Принимая во внимание единицу, которая | + | # Принимая во внимание единицу, которая станет первым (самая значащим) битом целого числа, со значением 2<sup>N</sup>, считать оставшиеся N цифр целого числа. |
Гамма-кодирование используется в приложениях, где самое большое значение не может быть известно заранее, или чтобы сжать данные, в которых маленькие значения встречаются более часто чем большие. | Гамма-кодирование используется в приложениях, где самое большое значение не может быть известно заранее, или чтобы сжать данные, в которых маленькие значения встречаются более часто чем большие. | ||
Строка 64: | Строка 64: | ||
== Обобщение == | == Обобщение == | ||
<!-- на этот заголовок есть ссылки из других статей --> | <!-- на этот заголовок есть ссылки из других статей --> | ||
− | Гамма-кодирование не подходит для кодирования нулевых значений или отрицательных чисел. | + | Гамма-кодирование не подходит для кодирования нулевых значений или отрицательных чисел. Один из способов закодировать ноль — прибавить ко всем числам 1 до кодирования и отнять после декодирования. Другой способ — приписать в начале любого ненулевого кода 1 , а затем кодировать ноль как простой 0. Единственный способ закодировать все целые числа — перед началом кодирования установить [[биекция|биекцию]] (соответствие), отображая целые числа из (0, 1, −1, 2, −2, 3, −3, …) в (1, 2, 3, 4, 5, 6, 7, …). |
== Пример программного кода == | == Пример программного кода == | ||
Строка 73: | Строка 73: | ||
IntReader intreader(source); | IntReader intreader(source); | ||
BitWriter bitwriter(dest); | BitWriter bitwriter(dest); | ||
− | + | while(intreader.hasLeft()) | |
− | while (intreader.hasLeft()) | ||
{ | { | ||
int num = intreader.getInt(); | int num = intreader.getInt(); | ||
− | int | + | int l = log2(num); |
− | + | for (int a=0; a < l; a++) | |
− | |||
− | for (int a = | ||
{ | { | ||
− | bitwriter.putBit(false); | + | bitwriter.putBit(false); //поместить нули, чтобы показать, сколько бит будут следовать |
} | } | ||
− | + | bitwriter.putBit(true); //пометить конец нолей | |
− | // | + | for (int a = l-1; a >= 0; a--) //записать биты как простые двоичные числа |
− | for (int a = | ||
{ | { | ||
if (num & (1 << a)) | if (num & (1 << a)) | ||
− | + | bitwriter.putBit(true); | |
else | else | ||
− | + | bitwriter.putBit(false); | |
} | } | ||
} | } | ||
− | |||
intreader.close(); | intreader.close(); | ||
bitwriter.close(); | bitwriter.close(); | ||
} | } | ||
− | |||
// Декодирование | // Декодирование | ||
void eliasGammaDecode(char* source, char* dest) | void eliasGammaDecode(char* source, char* dest) | ||
{ | { | ||
BitReader bitreader(source); | BitReader bitreader(source); | ||
− | + | BitWriter bitwriter(dest); | |
− | + | int numberBits = 0; | |
− | while (bitreader.hasLeft()) | + | while(bitreader.hasLeft()) |
{ | { | ||
− | + | while(!bitreader.getBit() || bitreader.hasLeft())numberBits++; //продолжить чтение пока не встретится единица... | |
− | + | int current = 0; | |
− | + | for (int a=0; a < numberBits; a++) //прочитать numberBits битов | |
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
{ | { | ||
− | + | if (bitreader.getBit()) | |
− | + | current += 1 << a; | |
− | |||
− | |||
− | |||
} | } | ||
− | + | //записать его как 32-битное число | |
− | + | ||
− | + | current = current | ( 1 << numberBits ) ;//последний бит не декодируется! | |
− | + | for (int a=0; a < 32; a++) //прочитать numberBits битов | |
− | for (; | ||
{ | { | ||
− | if ( | + | if (current & (1 << a)) |
− | + | bitwriter.putBit(true); | |
− | + | else | |
− | + | bitwriter.putBit(false); | |
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
} | } | ||
− | |||
− | |||
} | } | ||
− | |||
− | |||
− | |||
} | } | ||
</source> | </source> | ||
Строка 162: | Строка 125: | ||
* [[Омега-код Элиаса]] | * [[Омега-код Элиаса]] | ||
* [[Дельта-код Элиаса]] | * [[Дельта-код Элиаса]] | ||
+ | == Литература == | ||
+ | * {{статья |author-first=Peter |author-last=Elias |заглавие=Universal codeword sets and representations of the integers |издание={{Нп3|IEEE Transactions on Information Theory}} |том=21 |номер=2 |страницы=194—203 |ссылка=http://ieeexplore.ieee.org/xpl/freeabs_all.jsp?arnumber=1055349 |doi=10.1109/tit.1975.1055349 |язык=en |тип=journal |месяц=3 |год=1975}} | ||
+ | |||
+ | {{Методы сжатия}} | ||
[[Категория:Алгоритмы сжатия без потерь]] | [[Категория:Алгоритмы сжатия без потерь]] | ||
− | |||
− | |||
− | |||
− | |||
− | |||
− |
Текущая версия от 00:51, 20 августа 2025
Гамма-код Элиаса — это универсальный код для кодирования положительных целых чисел, разработанный Питером Элиасом. Он обычно используется при кодировании целых чисел, максимальное значение которых не может быть определено заранее.
Описание алгоритма[править | править код]
Чтобы закодировать число:
- Записать его в двоичной форме.
- Перед двоичным представлением числа дописать нули. Количество нулей на единицу меньше количества битов двоичного представления числа.
Аналогичный способ описания этого процесса:
- Выделить из целого числа старший значащий бит (самую большую степень 2, которую число включает — 2N) и младшие N бит.
- Записать N в унарном коде; то есть N нолей, за которыми следует единица.
- Дописать N младших двоичных цифр числа следом за этим унарным кодом.
Начало кодирования:
Число | Значение | Кодирование | Предполагаемая вероятность |
---|---|---|---|
1 | 20 + 0 | 1 | 1/2 |
2 | 21 + 0 | 0 1 0 | 1/8 |
3 | 21 + 1 | 0 1 1 | 1/8 |
4 | 2² + 0 | 00 1 00 | 1/32 |
5 | 2² + 1 | 00 1 01 | 1/32 |
6 | 2² + 2 | 00 1 10 | 1/32 |
7 | 2² + 3 | 00 1 11 | 1/32 |
8 | 2³ + 0 | 000 1 000 | 1/128 |
9 | 2³ + 1 | 000 1 001 | 1/128 |
10 | 2³ + 2 | 000 1 010 | 1/128 |
11 | 2³ + 3 | 000 1 011 | 1/128 |
12 | 2³ + 4 | 000 1 100 | 1/128 |
13 | 2³ + 5 | 000 1 101 | 1/128 |
14 | 2³ + 6 | 000 1 110 | 1/128 |
15 | 2³ + 7 | 000 1 111 | 1/128 |
16 | 24 + 0 | 0000 1 0000 | 1/512 |
17 | 24 + 1 | 0000 1 0001 | 1/512 |
… |
Распределение предполагаемых вероятностей для кодов добавлено для ясности.
Чтобы декодировать закодированное гамма-кодом Элиаса число следует:
- Считать все нули, встречающиеся до первой 1. Пусть N — количество этих нулей.
- Принимая во внимание единицу, которая станет первым (самая значащим) битом целого числа, со значением 2N, считать оставшиеся N цифр целого числа.
Гамма-кодирование используется в приложениях, где самое большое значение не может быть известно заранее, или чтобы сжать данные, в которых маленькие значения встречаются более часто чем большие.
Обобщение[править | править код]
Гамма-кодирование не подходит для кодирования нулевых значений или отрицательных чисел. Один из способов закодировать ноль — прибавить ко всем числам 1 до кодирования и отнять после декодирования. Другой способ — приписать в начале любого ненулевого кода 1 , а затем кодировать ноль как простой 0. Единственный способ закодировать все целые числа — перед началом кодирования установить биекцию (соответствие), отображая целые числа из (0, 1, −1, 2, −2, 3, −3, …) в (1, 2, 3, 4, 5, 6, 7, …).
Пример программного кода[править | править код]
// Кодирование
void eliasGammaEncode(char* source, char* dest)
{
IntReader intreader(source);
BitWriter bitwriter(dest);
while(intreader.hasLeft())
{
int num = intreader.getInt();
int l = log2(num);
for (int a=0; a < l; a++)
{
bitwriter.putBit(false); //поместить нули, чтобы показать, сколько бит будут следовать
}
bitwriter.putBit(true); //пометить конец нолей
for (int a = l-1; a >= 0; a--) //записать биты как простые двоичные числа
{
if (num & (1 << a))
bitwriter.putBit(true);
else
bitwriter.putBit(false);
}
}
intreader.close();
bitwriter.close();
}
// Декодирование
void eliasGammaDecode(char* source, char* dest)
{
BitReader bitreader(source);
BitWriter bitwriter(dest);
int numberBits = 0;
while(bitreader.hasLeft())
{
while(!bitreader.getBit() || bitreader.hasLeft())numberBits++; //продолжить чтение пока не встретится единица...
int current = 0;
for (int a=0; a < numberBits; a++) //прочитать numberBits битов
{
if (bitreader.getBit())
current += 1 << a;
}
//записать его как 32-битное число
current = current | ( 1 << numberBits ) ;//последний бит не декодируется!
for (int a=0; a < 32; a++) //прочитать numberBits битов
{
if (current & (1 << a))
bitwriter.putBit(true);
else
bitwriter.putBit(false);
}
}
}
См. также[править | править код]
Литература[править | править код]
- Universal codeword sets and representations of the integers (англ.) // IEEE Transactions on Information Theory[англ.] : journal. — 1975. — March (vol. 21, no. 2). — P. 194—203. — doi:10.1109/tit.1975.1055349.
Ошибка Lua в Модуль:Navbox на строке 353: attempt to index local 'listText' (a nil value).