Eliasovo gama kódování

Eliasův gama kód je univerzální kód pro kladná celá čísla, jehož autorem je Peter Elias. Nejčastější využití je kódování celých čísel, u kterých není předem zjistitelná jejich horní hranice, nebo ke kompresi dat, ve kterých jsou malé hodnoty mnohem častější než velké.

Zakódování

Pro zakódování libovolného přirozeného (tj. celého kladného) čísla:

  1. Zapište číslo ve dvojkové soustavě. Nechť N je počet cifer zápisu (tj. první jednička má váhu 2N–1).
  2. Před dvojkový zápis předřaďte N–1 nul.

Začátek kódu včetně pravděpodobnostního rozdělení, jenž je zmíněno pro přehlednost:

ČísloBinární reprezentace číslaZakódované čísloPravděpodobnost
1 = 20 + 0111/2
2 = 21 + 01 00 1 01/8
3 = 21 + 11 10 1 11/8
4 = 22 + 01 0000 1 001/32
5 = 22 + 11 0100 1 011/32
6 = 22 + 21 1000 1 101/32
7 = 22 + 31 1100 1 111/32
8 = 23 + 01 000000 1 0001/128
9 = 23 + 11 001000 1 0011/128
10 = 23 + 21 010000 1 0101/128
11 = 23 + 31 011000 1 0111/128
12 = 23 + 41 100000 1 1001/128
13 = 23 + 51 101000 1 1011/128
14 = 23 + 61 110000 1 1101/128
15 = 23 + 71 111000 1 1111/128
16 = 24 + 01 00000000 1 00001/512
17 = 24 + 11 00010000 1 00011/512

Dekódování

  1. Čtěte a počítejte nuly, dokud nedosáhnete první jedničky. Nechť je tento počet nul N–1.
  2. První dosažená jednička představuje dvojkovou číslici N ciferného čísla, tj. číslici s vahou 2N–1. Čtěte zbývajících N–1 dvojkových cifer.

Zobecnění

Gama kódování nekóduje nulu nebo záporná celá čísla. Způsob, jak zachytit nulu, je přičíst 1 před zakódováním a odečíst 1 po dekódování. Jiný způsob je dát 1 před každou nenulovou hodnotu a zakódovat nulu jako 0. Způsob jak zakódovat všechna celá čísla je udělat bijekci, která zobrazí čísla (0, 1, -1, 2, -2, 3, -3, ...) na (1, 2, 3, 4, 5, 6, 7, ...) před zakódováním.

Příklad zdrojového kódu

Zakódování v jazyce C:

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); //put 0s to indicate how much bits that will follow
      }
      bitwriter.putBit(true); //mark the end of the 0s
      for (int a=0; a < l; a++) //Write the bits as plain binary
      {
                  if (num & 1 << a)
                     bitwriter.putBit(true);
                  else
                     bitwriter.putBit(false);
      }
     }
     intreader.close();
     bitwriter.close();
}

Dekódování:

void eliasGammaDecode(char* source, char* dest)
{
     BitReader bitreader(source);
     BitWriter bitwriter(dest);
     int numberBits = 0;
     while(bitreader.hasLeft())
     {
        while(!bitreader.getBit() || bitreader.hasLeft())numberBits++; //keep on reading until we fetch a one...
        int current = 0;
        for (int a=0; a < numberBits; a++) //Read numberBits bits
        {
            if (bitreader.getBit())
               current += 1 << a;
        }
        //write it as a 32 bit number
        
        current= current | ( 1 << numberBits ) ;              //last bit isn't encoded!
        for (int a=0; a < 32; a++) //Read numberBits bits
        {
            if (current & (1 << a))
               bitwriter.putBit(true);
            else
               bitwriter.putBit(false);
        }
     }
}

Reference

V tomto článku byl použit překlad textu z článku Elias gamma coding na anglické Wikipedii.