тексту “еаіі!” буде –log 0,3 – log 0,2 – log 0,1 – log 0,1 – log 0,1 = – log 0,00006 4,22. (Тут застосовуємо логариф з основою 10, бо вищенаведене кодування виконувалося для десяткових чисел). Це пояснює, чому потрібно 5 десяткових цифр для кодування цього тексту. Таким чином, ширина підсумкового інтервалу є 0,2336 – 0, 23354 = 0,00006, а ентропія – від’ємний десятковий логарифм цього числа. Звичайно ми працюємо з двійковою арифметикою, передаємо двійкові числа та вимірюємо ентропію в бітах.
П’яти десяткових цифр здається забагато для кодування тексту з чотирьох голосних! Мабуть не зовсім вдало бу закінчувати приклад розгортанням, а не зтисканням. Однак зрозуміло, що різні моделі дають різну ентропію. Краща модель, побудована на аналізі окремих символів тексту “еаіі!”, є така множина частот символів: {“е” (0,2), “а” (0,2), “і” (0,4), “!” (0,2) }. Вона дає ентропію, що дорівнює 2,89 в десятковій системі відліку, тобто кодує вихідний текст числом з трьох цифр. Однак, більш складні моделі, як відмічалося раніше, дають в загальному випадку набагато кращій результат.
3. Програма для арифметичного кодування.
На рисунку 1 показано фрагмент псевдокоду, який поєднує процедури кодування та декодування, які було викладено в попередньому розділі. Символи в ньому нумеруються як 1, 2, 3… Частотний інтервал для і-того символу задається від cum_freeq[i] до cum_freeq[i-1]. При зменшенні і cum_freeq[i] зростає так, що cum_freeq[0] = 1. (Причина такого “зворотнього” договору полягає в тому, що cum_freeq[0] буде потім містити нормалізуючий множник, який зручно зберігати на початку масиву). Поточний робочий інтервал задається в [low; high] і буде в самому початку дорівнювати [0; 1) і для кодувальника, і для декодувальника.
На жаль, цей псевдокод значно спрощений, тоді як в практичному застосуванні існує декілька чинників, які ускладнюють і кодування, і декодування.
3.1 Алгоритм арифметичного кодування.
/*З кожним наступним символом тексту звертатися */
/*до процедури encode_symbol() */
/*Перевірити, що термінальний символ закодований останнім*/
/*Вивести одержане значення інтервалу [low; high) */
encode_symbol(symbol, cum_freq)
range = high – low
high = low + range*cum_freq[symbol - 1]
low = low + range*cum_freq[symbol]
3.2 Алгоритм арифметичного декодування.
/* Value – це число, яке одержано на вхід*/
/*Звертання до процедури decode_symbol() до того моменту*/
/*поки вона не поверне термінальний символ*/
decode_symbol(cum_freq)
пошук такого символу, що
cum_freq[symbol] <= (value - low) / (high - low) < cum_freq[symbol - 1]
/*це забезпечує розміщення Value в межах нового інтервалу*/
/*[low; high], що відображено в завершенні програми*/
range = high – low
high = low + range*cum_freq[symbol - 1]
low = low + range*cum_freq[symbol]
return symbol
Рисунок 1. Псевдокод арифметичного кодування та декодування.
4. Зауваження до реалізації.
4.1 Прирощувані передача і отримання інформації.
Наведений алгоритм кодування нічого не передає до повного завершення кодування всього тексту, а також і декодувальник не починає цей процес, поки не отримає стиснений текст цілком. Для більшості випадків необхіден поетапний режим виконання .
4.2 Бажане використання цілочисленої арифметики.
Потрібна для представлення інтервалу [low; high] точність зростає разом з довжиною тексту. Поетапне виконання допомагає вирішити цю проблему, але вимагає при цьому уважного обліку можливого переповнення та від’ємного переповнення.
4.3 Ефективна реалізація моделі.
Реалізація моделі повинна мінімізувати час визначення наступного символу алгоритмом декодування. Крім того, адаптивні моделі повинні також мінімізувати час, який вимагається для підтримання накопичених частот.
5. Реалізація моделі.
Сама реалізація буде обговорюватися в наступному розділі, а тут треба лише торкнутися тільки інтерфейсу з моделлю. Як відомо, байт представляє собою ціле число від 0 до 255 (тип char). Тут ми представляємо байт як ціле число від 1 до 257 включно (тип index), де EOF трактується як 257-й символ. Було б добре відсортувати модель в порядку зменшення частот для мінімізації кількості виконання циклу декодування. Перетворення з типу char в index, та навпаки, реалізовано за допомогою двох таблиць – index_to_char[] i char_to_index[]. В адаптивній моделі виконується перекодування, яке присвоює найчастішим символам маленькі індекси.
Ймовірності представляються в моделі як цілочиселені лічильники частот, а накопичувані частоти зберігаються в масиві cum_freq[]. Як і в попередньому випадку, цей масив – “зворотній”, і лічильник загальної частоти, який використовується для нормалізації всіх частот, розміщується в cum_freq[0]. Накопичувані частоти не повинні перевищувати встановленний в Max_frequency максимум, а реалізація моделі повинна запобігати переповненню відповідним маштабуванням. Необхідно також принаймні на 1 забезпечити різницю між двома сусідними значеннями cum_freq[], в противному випадку символ, що переглядається, не буде переданий.
6. Доведення правильності декодування.
Перевіримо правильність визначення процедурою decode_symbol() наступного символу. З псевдокоду на рисунку 1 зрозуміло, що decode_symbol() повинна використовувати Value для пошуку символа, який при кодуванні скоротив робочий інтервал так, що він продовжує включати в себе Value. В робочій програмі в decode_symbol() визначається такий символ, для якого:
cum_freq [symbol] ((value – low +1)*cum_freq [0]–1)/(high – low + 1) < cum_freq [symbol - 1], де означає операцію взяття цілої частини – ділення з відкиданням дробової частини. Показано, що це передбачає:
low + ((high - low + 1)*cum_freq [symbol]) / cum_freq [0] value low + ((high – low +1)*cum_freq [symbol - 1]) / cum_freq [0], таким чином, що value належить новому інтервалу, який вираховується процедурою decode_symbol(). Це гарантує коректність визначення кожного символу операцієй декодування.
7. Проблема переповнення і завершення кодування.
7.1 Від’ємне переповнення.
Як показано в псевдокоді, аріфметичне кодування працює за допомогою масштабування накопичених ймовірностей, які надаються моделю в інтервалі [low; high] для кожного символу, що передається. Припустимо, що low i high так близькі один до