La idea principal con la compresión aritmética es su capacidad de codificar probabilidad utilizando la cantidad exacta de longitud de datos requerida.
Esta cantidad de datos es conocido, probado por Shannon, y puede calcularse simplemente usando la siguiente fórmula: -log2 (p)
Por ejemplo, si p = 50%, entonces se necesita 1 bit. Y si p = 25%, necesita 2 bits.
Eso es lo suficientemente simple para probabilidades que son potencia de 2 (y en este caso especial, la codificación de huffman podría ser suficiente). Pero, ¿y si la probabilidad es del 63%? Entonces necesitas -log2 (0.63) = 0.67 bits. Suena complicado ...
Esta propiedad es especialmente importante si su probabilidad es alta. Si puede predecir algo con un 95% de precisión, solo necesita 0.074 bits para representar una buena suposición. Lo que significa que vas a comprimir mucho.
Ahora, ¿cómo hacer eso?
Bueno, es más simple de lo que parece. Usted dividirá su rango dependiendo de las probabilidades. Por ejemplo, si tiene un rango de 100, 2 eventos posibles y una probabilidad del 95% para el primero, los primeros 95 valores indicarán "Evento 1" y los últimos 5 valores restantes indicarán "Evento 2". .
Bien, pero en las computadoras, estamos acostumbrados a usar poderes de 2. Por ejemplo, con 16 bits, tiene un rango de 65536 valores posibles. Haga lo mismo: tome el primer 95% del rango (que es 62259) para decir "Evento 1", y el resto para decir "Evento 2". Obviamente tiene un problema de "redondeo" (precisión), pero siempre que tenga valores suficientes para distribuir, no importa demasiado. Además, no estás obligado a 2 eventos, podrías tener una gran cantidad de eventos. Todo lo que importa es que los valores se asignan según las probabilidades de cada evento.
Bien, pero ahora tengo 62259 valores posibles para decir "Evento 1" y 3277 para decir "Evento 2". Cuál debería elegir ? Bueno, cualquiera de ellos servirá. Ya sea 1, 30, 5500 o 62256, todavía significa "Evento 1".
De hecho, decidir qué valor seleccionar no dependerá de la conjetura actual, sino de las siguientes.
Supongamos que estoy teniendo "Evento 1". Así que ahora tengo que elegir cualquier valor entre 0 y 62256. En la próxima estimación, tengo la misma distribución (95% Evento 1, 5% Evento 2). Simplemente asignaré el mapa de distribución con estas probabilidades. Excepto que esta vez, se distribuye en 62256 valores. Y continuamos así, reduciendo el rango de valores con cada conjetura.
De hecho, estamos definiendo "rangos", que se estrechan con cada conjetura. En algún momento, sin embargo, hay un problema de precisión, porque quedan muy pocos valores.
La idea es simplemente "inflar" el rango nuevamente. Por ejemplo, cada vez que el rango está por debajo de 32768 (2^15), se obtiene la salida del bit más alto y se multiplica el resto por 2 (cambiando efectivamente los valores por un bit a la izquierda). Al hacer esto de manera continua, está produciendo bits uno por uno, ya que están siendo resueltos por la serie de suposiciones.
Ahora la relación con la compresión se vuelve obvia: cuando el rango se reduce rápidamente (por ejemplo, 5%), se generan muchos bits para volver al rango por encima del límite. Por otro lado, cuando la probabilidad es muy alta, el rango se estrecha muy lentamente. Incluso puede tener muchas suposiciones antes de enviar sus primeros bits. Así es como es posible comprimir un evento a "una fracción de un bit".
He utilizado intencionalmente los términos "probabilidad", "adivinar", "eventos" para mantener este artículo genérico. Pero para la compresión de datos, solo tiene que reemplazarlos con la forma en que desea modelar sus datos. Por ejemplo, el próximo evento puede ser el siguiente byte; en este caso, tienes 256 de ellos.
Ahora entiendo la pregunta. –
Puede encontrar una explicación muy detallada para la codificación aritmética y los algoritmos [en este artículo de Arturo San Emeterio Campos] (http://www.arturocampos.com/ac_arithmetic.html). También puede ver una implementación de C++ para estos algoritmos en [esta publicación] (http://stackoverflow.com/a/10017164/1009831). –