Гамма-код Элиаса: различия между версиями

Материал из in.wiki
Перейти к навигации Перейти к поиску
м (45 версий импортировано: Импорт из Википедии)
 
(не показано 11 промежуточных версий 9 участников)
Строка 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 || 01 0 || 1/8
+
| 2 || 2<sup>1</sup> + 0 || 0 1 0 || 1/8
 
|-
 
|-
| 3 || 2<sup>1</sup> + 1 || 01 1 || 1/8
+
| 3 || 2<sup>1</sup> + 1 || 0 1 1 || 1/8
 
|-
 
|-
| 4 || 2² + 0 || 001 00 || 1/32
+
| 4 || 2² + 0 || 00 1 00 || 1/32
 
|-
 
|-
| 5 || 2² + 1 || 001 01 || 1/32
+
| 5 || 2² + 1 || 00 1 01 || 1/32
 
|-
 
|-
| 6 || 2² + 2 || 001 10 || 1/32
+
| 6 || 2² + 2 || 00 1 10 || 1/32
 
|-
 
|-
| 7 || 2² + 3 || 001 11 || 1/32
+
| 7 || 2² + 3 || 00 1 11 || 1/32
 
|-
 
|-
| 8 || 2³ + 0 || 0001 000 || 1/128
+
| 8 || 2³ + 0 || 000 1 000 || 1/128
 
|-
 
|-
| 9 || 2³ + 1 || 0001 001 || 1/128
+
| 9 || 2³ + 1 || 000 1 001 || 1/128
 
|-
 
|-
|10 || 2³ + 2 || 0001 010 || 1/128
+
|10 || 2³ + 2 || 000 1 010 || 1/128
 
|-
 
|-
|11 || 2³ + 3 || 0001 011 || 1/128
+
|11 || 2³ + 3 || 000 1 011 || 1/128
 
|-
 
|-
|12 || 2³ + 4 || 0001 100 || 1/128
+
|12 || 2³ + 4 || 000 1 100 || 1/128
 
|-
 
|-
|13 || 2³ + 5 || 0001 101 || 1/128
+
|13 || 2³ + 5 || 000 1 101 || 1/128
 
|-
 
|-
|14 || 2³ + 6 || 0001 110 || 1/128
+
|14 || 2³ + 6 || 000 1 110 || 1/128
 
|-
 
|-
|15 || 2³ + 7 || 0001 111 || 1/128
+
|15 || 2³ + 7 || 000 1 111 || 1/128
 
|-
 
|-
|16 || 2<sup>4</sup> + 0 || 00001 0000 || 1/512
+
|16 || 2<sup>4</sup> + 0 || 0000 1 0000 || 1/512
 
|-
 
|-
|17 || 2<sup>4</sup> + 1 || 00001 0001 || 1/512
+
|17 || 2<sup>4</sup> + 1 || 0000 1 0001 || 1/512
 
|-
 
|-
 
|… || || ||
 
|… || || ||
Строка 64: Строка 64:
 
== Обобщение ==
 
== Обобщение ==
 
<!-- на этот заголовок есть ссылки из других статей -->
 
<!-- на этот заголовок есть ссылки из других статей -->
Гамма-кодирование не подходит для кодирования нулевых значений или отрицательных чисел. Единственный способ закодировать ноль — прибавить к нему 1 до кодирования и отнять после декодирования. Другой способ — приписать в начале любой ненулевой код с 1 , а затем кодировать ноль как простой 0. Единственный способ закодировать все целые числа — перед началом кодирования установить [[биекция|биекцию]] (соответствие), отображая целые числа из (0, 1, −1, 2, −2, 3, −3, …) в (1, 2, 3, 4, 5, 6, 7, …).
+
Гамма-кодирование не подходит для кодирования нулевых значений или отрицательных чисел. Один из способов закодировать ноль — прибавить ко всем числам 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 l = log2(num);
 
       int l = log2(num);
Строка 81: Строка 82:
 
       }
 
       }
 
       bitwriter.putBit(true); //пометить конец нолей
 
       bitwriter.putBit(true); //пометить конец нолей
       for (int a=0; a < l; a++) //записать биты как простые двоичные числа
+
       for (int a = l-1; a >= 0; a--) //записать биты как простые двоичные числа
 
       {
 
       {
                  if (num & (1 << a))
+
          if (num & (1 << a))
                    bitwriter.putBit(true);
+
            bitwriter.putBit(true);
                  else
+
          else
                    bitwriter.putBit(false);
+
            bitwriter.putBit(false);
 
       }
 
       }
 
     }
 
     }
Строка 124: Строка 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

Гамма-код Элиаса — это универсальный код для кодирования положительных целых чисел, разработанный Питером Элиасом. Он обычно используется при кодировании целых чисел, максимальное значение которых не может быть определено заранее.

Описание алгоритма[править | править код]

Чтобы закодировать число:

  1. Записать его в двоичной форме.
  2. Перед двоичным представлением числа дописать нули. Количество нулей на единицу меньше количества битов двоичного представления числа.

Аналогичный способ описания этого процесса:

  1. Выделить из целого числа старший значащий бит (самую большую степень 2, которую число включает — 2N) и младшие N бит.
  2. Записать N в унарном коде; то есть N нолей, за которыми следует единица.
  3. Дописать 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. Считать все нули, встречающиеся до первой 1. Пусть N — количество этих нулей.
  2. Принимая во внимание единицу, которая станет первым (самая значащим) битом целого числа, со значением 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);
        }
     }
}

См. также[править | править код]

Литература[править | править код]

Ошибка Lua в Модуль:Navbox на строке 353: attempt to index local 'listText' (a nil value).