Особенности реализации метода одномерного кодирования данных
Процесс кодирования невозможно реализовать на практике, так как в нем предполагается, что в переменных Low и High хранятся числа с неограниченной точностью. Процесс декодирования, («Далее декодер удаляет эффект символа S из кода с помощью вычитания ... и деления ...») по своей сути очень прост, но совершенно не практичен. Код, который является одним числом, обычно будет длинным, очень длинным числом. Файл объема 1 MB будет сжиматься, скажем, до 500 KB, в котором будет записано всего одно число. Деление чисел в 500 KB делается очень сложно и долго.
Любое практическое применение арифметического кодирования должно основываться на оперировании с целыми числами (арифметика чисел с плавающей запятой работает медленно и при этом происходит потеря точности), которые не могут быть слишком длинными. Мы опишем такую реализацию с помощью двух целых переменных Low и High. В нашем примере они будут иметь длину в 4 десятичные цифры, но на практике будут использоваться целые длиной 16 или 32 бита. Эти переменные будут хранить верхний и нижний концы текущего подынтервала, но мы не будем им позволять неограниченно расти. Как только самые левые цифры переменных Low и High становятся одинаковыми, они уже не меняются в дальнейшем. Поэтому мы будем выдвигать эти числа за пределы переменных Low и High и сохранять их в выходном файле.
Таким образом, эти переменные будут хранить не весь код, а только самую последнюю его часть. После сдвига цифр мы будем справа дописывать О в переменную Low, а в переменную High - цифру 9. Для того, чтобы лучше понять весь процесс, можно представлять себе эти переменные как левый конец бесконечно длинного числа. Проблема состоит в том, что переменная High в начале должна равняться 1, однако мы интерпретируем Low и High как десятичные дроби меньшие 1. Решение заключается в присвоении переменной High значения 9999... , которое соответствует бесконечной дроби 0.9999... , равной 1.
(Это легко доказать. Если 0.9999.. . < 1, то среднее число а = (0.9999.. . + 1) /2 должно лежать между 0.9999 .. . и 1; однако, его невозможно выразить десятичной дробью. Нельзя добавить ни одной цифры к числу 0.9999... , поскольку в нем бесконечно много цифр. Также ни одну из его цифр нельзя увеличить, так как все они равны 9. Значит, число 0.9999.. . равно 1. Рассуждая аналогично, легко показать, что число 0.5 имеет два представления в виде двоичной дроби: 0.1000.. . и 0.0111...).
Процесс кодирования строки символов «SWISS-MISS». В первом столбце записаны символы на входе. Столбец 2 содержит новые значения переменных Low и High. В третьем столбце эти числа представлены в измененном масштабе с уменьшением High на 1. Строка 4 показывает следующую цифру, носылаемую на выход, а в пятом столбце записаны Low и High после их сдвига влево на одну цифру. Заметьте, что на последнем шаге в выходной файл было записано четыре цифры 3750. Окончательный выходной файл имеет вид 717533750.
Декодер работает в обратном порядке. В начале сделаны присвоения Low=0000, High=9999, и Code=7175 (первые четыре цифры сжатого файла). Эти переменные обновляются на каждом шаге процедуры декодирования. Low и High приближаются друг к другу (и к Code) до тех пор, пока их самые значимые цифры не будут совпадать. Тогда они сдвигаются влево, что приводит к их разделению, Code тоже сдвигается. На каждом шаге вычисляется переменная index, которая используется для нахождения столбца CumFreq, позволяющего определить текущий символ.
Теперь ясно, что символ eof следует добавлять в исходную таблицу частот и вероятностей. Этот символ будет кодироваться и декодироваться последним, что будет служить сигналом для остановки процесса.
- RSS
Наши услуги: