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

Материал из in.wiki
Перейти к навигации Перейти к поиску
w>TXiKiBoT
м (робот добавил: fr:Codage gamma)
м (45 версий импортировано: Импорт из Википедии)
 
(не показано 26 промежуточных версий 18 участников)
Строка 4: Строка 4:
 
Чтобы закодировать число:
 
Чтобы закодировать число:
 
# Записать его в двоичной форме.
 
# Записать его в двоичной форме.
# Перед двоичным представлением числа дописать нули. Количество нолей на единицу меньше количества битов двоичного представления числа.
+
# Перед двоичным представлением числа дописать нули. Количество нулей на единицу меньше количества битов двоичного представления числа.
  
 
Аналогичный способ описания этого процесса:
 
Аналогичный способ описания этого процесса:
# Разделить целое число на самую большую степень 2, которую оно включает (2<sup>N</sup>), и на оставшиеся N двоичных цифр от данного целого числа.
+
# Выделить из целого числа старший значащий бит (самую большую степень 2, которую число включает — 2<sup>N</sup>) и младшие N бит.
# Записать N в унарном коде; то есть 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 || 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
 
|-
 
|-
 
|… || || ||
 
|… || || ||
Строка 58: Строка 58:
  
 
# Считать все нули, встречающиеся до первой 1. Пусть N — количество этих нулей.
 
# Считать все нули, встречающиеся до первой 1. Пусть N — количество этих нулей.
# Принимая во внимание единицу, которая была достигнута как первая цифра целого числа, со значением 2<sup>N</sup>, считать оставшиеся 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, …).
+
Гамма-кодирование не подходит для кодирования нулевых значений или отрицательных чисел. Один из способов закодировать ноль — прибавить ко всем числам 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 numberBits = log2(num);
+
       int l = log2(num);
 
+
       for (int a=0; a < l; a++)
      // поместить numberBits нулей, чтобы показать, сколько бит будут следовать
 
       for (int a = numberBits - 1; a >= 0; a--)
 
 
       {       
 
       {       
           bitwriter.putBit(false);
+
           bitwriter.putBit(false); //поместить нули, чтобы показать, сколько бит будут следовать
 
       }
 
       }
 
+
       bitwriter.putBit(true); //пометить конец нолей
       // скопировать (numberBits + 1) битов числа
+
       for (int a = l-1; a >= 0; a--) //записать биты как простые двоичные числа
       for (int a = numberBits; 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);
 
       }
 
       }
 
     }
 
     }
 
 
     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);
     IntWriter intwriter(dest);
+
     BitWriter bitwriter(dest);
 
+
    int numberBits = 0;
     while (bitreader.hasLeft())
+
     while(bitreader.hasLeft())
 
     {
 
     {
         int numberBits = 0;
+
         while(!bitreader.getBit() || bitreader.hasLeft())numberBits++; //продолжить чтение пока не встретится единица...
 
+
         int current = 0;
        // продолжить чтение пока не встретится единица...
+
         for (int a=0; a < numberBits; a++) //прочитать numberBits битов
         while (bitreader.getBit() == false)
 
         {
 
            numberBits++;
 
 
 
            if (!bitreader.hasLeft())
 
            {
 
                // неожиданный конец потока битов
 
                // аварийный выход
 
                // игнорируем уже прочитанные биты
 
                return;
 
            }
 
        }
 
 
 
        if (numberBits > (sizeof(int) * BITS_PER_BYTE - 1))
 
 
         {
 
         {
             // переполнение целочисленного типа
+
             if (bitreader.getBit())
            // входной поток содержит неверные данные
+
              current += 1 << a;
            // аварийный выход
 
            // игнорируем уже прочитанные биты
 
            return;
 
 
         }
 
         }
 
+
        //записать его как 32-битное число
         int num = 1;
+
 
+
         current = current | ( 1 << numberBits ) ;//последний бит не декодируется!
        // прочитать numberBits битов
+
         for (int a=0; a < 32; a++) //прочитать numberBits битов
         for (; numberBits > 0; numberBits--)
 
 
         {
 
         {
             if (!bitreader.hasLeft())
+
             if (current & (1 << a))
            {
+
              bitwriter.putBit(true);
                // неожиданный конец потока битов
+
             else
                // аварийный выход
+
              bitwriter.putBit(false);
                // игнорируем уже прочитанные биты
 
                return;
 
             }
 
 
 
            num = num << 1;
 
 
 
            if (bitreader.getBit() == true)
 
              num = num | 1;
 
 
         }
 
         }
 
        intwriter.putInt(num);
 
 
     }
 
     }
 
    intreader.close();
 
    bitwriter.close();
 
 
}
 
}
 
</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}}
 +
 +
{{Методы сжатия}}
  
 
[[Категория:Алгоритмы сжатия без потерь]]
 
[[Категория:Алгоритмы сжатия без потерь]]
 
[[cs:Eliasovo gama kódování]]
 
[[en:Elias gamma coding]]
 
[[fr:Codage gamma]]
 
[[ja:ガンマ符号]]
 
[[ko:엘리어스 감마 부호]]
 

Текущая версия от 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).