Введение

Кодирование диапазоном (или кодирование диапазонов) — это метод энтропийного кодирования, разработанный Г. Найджелом Н. Мартином в 1979 году, который фактически заново открыл FIFO арифметический код, впервые представленный Ричардом Кларком Паско в 1976 году. Получив поток символов и их вероятности, кодировщик диапазонов генерирует компактный поток битов для представления этих символов, а декодировщик диапазонов, получив этот поток и вероятности, восстанавливает исходные символы. Кодирование диапазоном очень похоже на арифметическое кодирование, за исключением того, что кодирование выполняется с использованием цифр в любой системе счисления, а не битов, и поэтому оно быстрее при использовании больших систем счисления (например, байта), хотя и с некоторой потерей эффективности сжатия. После истечения срока действия первого патента на арифметическое кодирование (1978 год) кодирование диапазоном оказалось свободным от патентных ограничений. Это особенно стимулировало интерес к этой технике в сообществе разработчиков открытого исходного кода. С тех пор срок действия патентов на различные известные методы арифметического кодирования также истек.

Как работает кодирование диапазона

Кодирование диапазоном концептуально кодирует все символы сообщения в одно число, в отличие от кодирования Хаффмана, которое присваивает каждому символу битовую последовательность и объединяет все эти последовательности вместе. Таким образом, кодирование диапазоном может достигать более высоких коэффициентов сжатия, чем нижняя граница в один бит на символ для кодирования Хаффмана, и не страдает от недостатков, присущих кодированию Хаффмана при работе с вероятностями, которые не являются точной степенью двойки. Основная идея кодирования диапазоном заключается в следующем: имея достаточно большой диапазон целых чисел и оценку вероятностей для символов, начальный диапазон можно легко разделить на поддиапазоны, размеры которых пропорциональны вероятности представляемого ими символа. Затем каждый символ сообщения кодируется последовательно, путем сужения текущего диапазона до поддиапазона, соответствующего следующему символу для кодирования. Декодер должен иметь ту же оценку вероятностей, что и кодер, которую можно передать заранее, вывести из уже переданных данных или включить в состав компрессора и декомпрессора. Когда все символы закодированы, достаточно просто определить поддиапазон, чтобы передать все сообщение (при условии, конечно, что декодер каким-то образом уведомляется о завершении извлечения сообщения). Для идентификации поддиапазона достаточно одного целого числа, и даже может не потребоваться передавать все число; если существует последовательность цифр, такая что любое целое число, начинающееся с этого префикса, попадает в поддиапазон, то для идентификации поддиапазона и, следовательно, для передачи сообщения достаточно только этого префикса.

Связь с арифметическим кодированием

Арифметическое кодирование тождественно кодированию диапазоном, но с использованием целых чисел в качестве числителей дробей. Эти дроби имеют неявный общий знаменатель, благодаря которому все дроби попадают в диапазон [0,1). Соответственно, результирующий арифметический код интерпретируется как начинающийся с неявного "0". Поскольку это лишь различные интерпретации одних и тех же методов кодирования, а полученные арифметические и диапазонные коды идентичны, каждый арифметический кодер является соответствующим кодировщиком диапазоном, и наоборот. Иными словами, арифметическое кодирование и кодирование диапазоном – это просто два немного отличающихся способа понимания одного и того же. На практике, однако, так называемые кодировщики диапазоном, как правило, реализуются примерно так, как описано в работе Мартина, в то время как арифметические кодировщики обычно не называют кодировщиками диапазоном. Часто отмечаемой особенностью таких кодировщиков диапазоном является тенденция выполнять ренормализацию побайтово, а не побитово (как это обычно делается). Другими словами, кодировщики диапазоном склонны использовать байты в качестве кодирующих разрядов, а не биты. Хотя это и немного снижает степень сжатия, это быстрее, чем выполнять ренормализацию для каждого бита.