L'idea principale con compressione aritmetica è la capacità di codificare una probabilità utilizzando la quantità esatta di lunghezza dei dati richiesta.
Questa quantità di dati è noto, provato da Shannon, e può essere calcolato semplicemente utilizzando la seguente formula: -log2 (p)
Ad esempio, se p = 50%, quindi è necessario 1 bit. E se p = 25%, hai bisogno di 2 bit.
Questo è abbastanza semplice per le probabilità che sono potenza di 2 (e in questo caso speciale, la codifica di huffman potrebbe essere sufficiente). Ma cosa succede se la probabilità è del 63%? Quindi è necessario -log2 (0.63) = 0.67 bit. Sembra difficile ...
Questa proprietà è particolarmente importante se la tua probabilità è alta. Se puoi prevedere qualcosa con un'accuratezza del 95%, allora hai solo bisogno di 0,074 bit per rappresentare una buona ipotesi. Il che significa che stai per comprimere molto.
Ora, come fare?
Bene, è più semplice di quanto sembri. Dividerai la tua gamma in base alle probabilità. Ad esempio, se hai un intervallo di 100, 2 possibili eventi e una probabilità del 95% per il primo, allora i primi 95 valori diranno "Evento 1" e gli ultimi 5 valori restanti diranno "Evento 2" .
OK, ma sui computer, siamo abituati a utilizzare le potenze di 2. Ad esempio, con 16 bit, avete un intervallo di 65536 valori possibili. Fai lo stesso: prendi il 1 ° 95% del range (che è 62259) per dire "Event 1", e il resto per dire "Event 2". Ovviamente hai un problema di "arrotondamento" (precisione), ma finché hai abbastanza valori da distribuire, non importa troppo. Inoltre, non sei vincolato a 2 eventi, potresti avere una miriade di eventi. Tutto ciò che conta è che i valori siano assegnati in base alle probabilità di ciascun evento.
OK, ma ora ho 62259 valori possibili per dire "Evento 1" e 3277 per dire "Evento 2". Quale dovrei scegliere? Beh, qualcuno di loro lo farà. Sia che sia 1, 30, 5500 o 62256, significa ancora "Evento 1".
In effetti, decidere quale valore selezionare non dipende dall'ipotesi corrente, ma da quelli successivi.
Supponiamo di avere "Evento 1". Così ora devo scegliere qualsiasi valore tra 0 e 62256. Il prossimo indovinare, ho la stessa distribuzione (95% Evento 1, 5% Evento 2). Alletterò semplicemente la mappa di distribuzione con queste probabilità. Tranne che questa volta, è distribuito su 62256 valori. E continuiamo così, riducendo l'intervallo di valori a ogni ipotesi.
Quindi, in effetti, stiamo definendo "intervalli", che restringono ad ogni ipotesi. Ad un certo punto, tuttavia, c'è un problema di accuratezza, perché rimangono pochissimi valori.
L'idea è semplicemente "gonfiare" di nuovo l'intervallo. Ad esempio, ogni volta che l'intervallo scende sotto 32768 (2^15), si emette il bit più alto e si moltiplica il resto per 2 (spostando in modo efficace i valori di un bit a sinistra). Continuando continuamente a fare questo, si emettono i bit uno per uno, poiché vengono risolti dalla serie di ipotesi.
Ora la relazione con la compressione diventa ovvia: quando l'intervallo viene ristretto rapidamente (es: 5%), si generano molti bit per riportare l'intervallo al di sopra del limite. D'altra parte, quando la probabilità è molto alta, la gamma si restringe molto lentamente. Puoi anche avere un sacco di ipotesi prima di emettere i tuoi primi bit. È così che è possibile comprimere un evento in "una frazione di un bit".
Ho usato volutamente il termine "probabilità", "indovinare", "eventi" per mantenere questo articolo generico. Ma per la compressione dei dati, è sufficiente sostituirli con il modo in cui si desidera modellare i dati. Ad esempio, il prossimo evento può essere il prossimo byte; in questo caso, ne hai 256.
Ora capisco la domanda. –
Puoi trovare una spiegazione molto dettagliata della codifica aritmetica e degli algoritmi [in questo articolo di Arturo San Emeterio Campos] (http://www.arturocampos.com/ac_arithmetic.html). Inoltre, è possibile vedere un'implementazione C++ per questi algoritmi in [questo post] (http://stackoverflow.com/a/10017164/1009831). –