Який найефективніший спосіб зберігання числового діапазону?


29

Це питання стосується того, скільки бітів потрібно для зберігання діапазону. Або кажучи іншим способом, для заданої кількості біт, який максимальний діапазон, який можна зберігати і як?

Уявіть, що ми хочемо зберігати піддіапазон у межах 0-255.

Так, наприклад, 45-74.

Ми можемо зберігати приклад вище як два неподписані байти, але мені вражає, що там повинно бути деяка надмірність інформації. Ми знаємо, що друге значення більше, ніж перше, тому у випадку, коли перше значення велике, потрібно менше біт для другого значення, а у випадку, коли друге значення велике, потрібно менше біт для першого .

Я підозрюю, що будь-яка техніка стиснення дасть граничний результат, тому може бути кращим питанням запитати "який максимальний діапазон, який можна зберегти в одному байті?". Це повинно бути більше, ніж досяжне, зберігаючи два числа окремо.

Чи існують якісь стандартні алгоритми виконання подібних речей?


Ви також повинні зберігати старт асортименту?
Еван

@Ewan Я насправді не стежу. У наведеному вище прикладі 45 - це початок (мінімум), а 74 - кінець (максимум), і обидва мають бути збережені.
rghome

2
так це питання, скільки місця потребує тип, який може зберігати будь-який діапазон. або скільки місця потребує тип, який може зберігати 45-74?
Еван

1
Хоча думати про це, безумовно, добре, я сподіваюся, що ви цього не зробите в реальних програмах. Причина полягає в тому, що обсяг складності реальних додатків настільки величезний, що нам доводиться приймати менше 100% оптимізованого коду .... Саме тому існували компілятори.
NoChance

3
@rghome, я згоден, навіть найпростіша вимога створює сотні рядків коду. Кожна з них схильна до помилок. Особисто я б заплатив за обладнання, ніж збільшив складність програмного забезпечення.
NoChance

Відповіді:


58

Просто порахуйте кількість можливих діапазонів. Є 256 діапазонів із нижньою межею 0 (0-0, 0-1, ... 0-254, 0-255), 255 діапазонів із нижньою межею 1, ... і, нарешті, 1 діапазон із нижньою межею 255 (255- 255). Отже загальна кількість дорівнює (256 + 255 + ... + 1) = 257 * 128 = 32 896. Оскільки це трохи вище 2 15 = 32 768, для зберігання цієї інформації вам все одно знадобиться принаймні 16 біт (2 байти).

Загалом для чисел від 0 до n-1 кількість можливих діапазонів дорівнює n * (n + 1) / 2. Це менше 256, якщо n дорівнює 22 або менше: n = 22 дає 22 * ​​23/2 = 253 можливості. Отже, одного байта достатньо для піддіапазонів 0-21 .

Ще один спосіб розглянути проблему полягає в наступному: зберігання пари цілих чисел у діапазоні від 0 до n-1 - майже те саме, що зберігати піддіапазон 0- (n-1) плюс один біт, який визначає, чи є перше число нижче або вище другого. (Різниця виникає в тому випадку, коли обидва цілих числа рівні, але цей шанс стає все меншим, коли n збільшується.) Ось чому за допомогою цієї техніки ви можете зберегти лише один біт, і, мабуть, головна причина, чому його рідко використовують.


Спасибі. Кількість бітів, необхідних для n діапазонів, - log (n) / log2. Подаючи все це у Вольфрам Альфа, я дав наступну сумісну формулу Excel для обчислення максимального значення піддіапазону для заданої кількості біт: = INT ((SQRT (POWER (2, N + 3) + 1) + 1) - 1) / 2 )
rghome

9
TLDR полягає в тому, що ви отримуєте близько половини трохи, так що в цілому стиснення насправді не варто.
rghome

Так, це має тенденцію до одного біта для великих N, але насправді це не варто.
Глорфіндель

FYI, N + 3 в рівнянні виглядає дивним, але одна сила 2 походить від вашого рівняння, а інші два - з 4ac частини квадратичної формули.
rghome

1
До речі, ваш підрахунок знижує порожній діапазон, на який стоять всі нелічені комбінації. Отже n * (n + 1) / 2 + 1,! Незначна зміна.
Дедуплікатор

17

Для такої невеликої кількості бітів неможливо зберегти багато бітів, як вказував Glorfindel . Однак якщо домен, який ви використовуєте, має ще кілька біт, ви можете досягти значної економії для середнього випадку, кодуючи діапазони із початковим значенням і дельтою.

Припустимо, домен - цілі числа, тому 32 біти. При наївному підході вам потрібно 64 біта (початок, кінець) для зберігання діапазону.

Якщо ми переходимо до кодування (start, delta), ми можемо побудувати з цього кінець діапазону. Ми знаємо, що в гіршому випадку старт дорівнює 0, а дельта має 32 біти.

2 ^ 5 - 32, тому ми кодуємо довжину дельти в п'ять біт (довжина нульова, завжди додаємо 1), і кодування стає (початок, довжина, дельта). У гіршому випадку це коштує 32 * 2 + 5 біт, тобто 69 біт. Так що в гіршому випадку, якщо всі діапазони довгі, це гірше, ніж наївне кодування.

У кращому випадку він коштує 32 + 5 + 1 = 38 біт.

Це означає, що якщо вам доведеться кодувати багато діапазонів, і ці діапазони покривають лише невелику частину вашого домену, ви в кінцевому рахунку використовуєте менше місця в середньому за допомогою цього кодування. Не має значення, як розповсюджуються пуски, оскільки старт завжди матиме 32 біти, але не важливо, як розподіляються довжини діапазонів. Якщо чим більше у вас невеликих довжин, тим краще стиснення, чим більше діапазонів у вас буде охоплювати всю довжину домену, тим гірше вийде таке кодування.

Однак якщо у вас багато діапазонів, згрупованих навколо подібних стартових точок (наприклад, тому що ви отримуєте значення від датчика), ви можете досягти ще більшої економії. Ви можете застосувати ту саму техніку до початкового значення та використовувати зміщення для компенсації стартового значення.

Скажімо, у вас 10000 діапазонів. Діапазони згруповані навколо певного значення. Ви кодуєте зміщення 32 біта.

Використовуючи наївний підхід, вам знадобиться 32 * 2 * 10 000 = 640 000 біт для зберігання всіх цих діапазонів.

Кодування зміщення займає 32 біти, а кодування кожного діапазону в кращому випадку займає 5 + 1 + 5 + 1 = 12 біт, загалом 120 000 + 32 = 120 032 біт. У гіршому випадку вам потрібно 5 + 32 + 5 + 32 біт, таким чином, 74 біта, загалом 740 032 біт.

Це означає, що для 10 000 значень у домені, який кодує 32 біти, ми отримуємо

  • 120 032 біт із розумним кодуванням дельта в кращому випадку
  • 640 000 біт з наївним початком, кінцевим кодуванням, завжди (ні в кращому, ні в гіршому випадку)
  • 740 032 біт з інтелектуальним кодуванням дельта в гіршому випадку

Якщо ви приймаєте наївне кодування за базовий рівень, це означає або економію до 81,25%, або до 15,625% більше витрат.

Залежно від розподілу ваших цінностей ці заощадження значні. Знайте свій бізнес-домен! Знайте, що ви хочете кодувати.

Як розширення, ви також можете змінити зміщення. Якщо ви аналізуєте дані та визначаєте групи значень, ви можете сортувати дані у відра та кодувати кожне з цих відроків окремо, з власним зміщенням. Це означає, що ви можете застосовувати цю техніку не тільки до діапазонів, які згруповані навколо одного початкового значення, але і до діапазонів, які згруповані навколо декількох значень.

Якщо вихідні точки розподілені однаково, це кодування насправді не так добре працює.

Це кодування очевидно вкрай погано індексувати. Ви не можете просто прочитати значення x-го. Його можна прочитати лише послідовно. Що доречно в деяких ситуаціях, наприклад, потокове передавання по мережі або масове зберігання (наприклад, на стрічці або жорсткому диску).

Оцінка даних, їх групування та вибір правильного зміщення може бути вагомою справою і може зажадати певної настройки для досягнення оптимальних результатів.


8

Такого роду проблема є предметом навчальної праці Клода Шеннона " Математична теорія зв'язку" , в якій було введено слово "біт" і більш-менш винайдене стиснення даних.

Загальна ідея полягає в тому, що кількість бітів, що використовуються для кодування діапазону, обернено пропорційна ймовірності виникнення цього діапазону. Наприклад, припустимо, що діапазон 45-74 з'являється приблизно в 1/4 часу. Можна сказати, що послідовність 00 відповідає 45-74. Для кодування діапазону 45-74 виводить "00" і зупиняється на цьому.

Припустимо також, що діапазони 99-100 та 140-155 з'являються приблизно в 1/8 часу. Ви можете кодувати кожну з них 3-бітною послідовністю. Будь-які 3 біти будуть виконуватись до тих пір, поки вони не почнуться з "00", що вже зарезервовано для діапазону 45-74.

00: 45-74
010: 99-100
101: 140-155

Ви можете продовжувати таким чином, поки кожен можливий діапазон не має кодування. Найменш вірогідний діапазон може потребувати понад 100 біт. Але це нормально, оскільки він рідко з'являється.

Там є алгоритми для пошуку оптимального кодування. Я не намагатимусь пояснити їх тут, але ви можете дізнатися більше, перейшовши за посиланням вище або шукаючи “Теорію інформації”, “Кодування Шеннона-Фано” або “Кодування Хаффмана”.

Як зазначали інші, можливо, краще зберігати початкове число та різницю між початковим та кінцевим номером. Ви повинні використовувати одне кодування для початку та інше для різниці, оскільки вони мають різний розподіл ймовірностей (і я здогадуюсь, останнє є більш зайвим). Як запропоновано поліномом, найкращий алгоритм залежить від вашого домену.


1
Так, ділова сфера дійсно важлива. Ми фактично розглядали можливість використання кодування Хаффмана для відхилень для дати початку, але врешті-решт вирішили проти цього після проведення статистичного аналізу реальних даних. Простота використання одного і того ж кодування для зміщення та дельти була важливішою, ніж додавання Хаффмана зверху, плюс вам також потрібно надіслати все дерево Хаффмана. Хороша ідея мати на увазі кодування Хаффмана.
Полігном

1

Щоб розширити відповідь від @Glorfindel:

Як n → ∞, (n - 1) → n. Таким чином, Ω (діапазони) → n² / 2 і log (Ω (діапазони)) → (2n - 1). Оскільки наївне кодування займає 2n біт, максимальне асимптотичне стиснення економить лише 1 біт.


1

Існує аналогічна відповідь, але для досягнення оптимальної компресії вам потрібно:

  1. Оптимальний метод кодування ентропії (зчитування з арифметичного кодування та фактично еквівалентний (той же коефіцієнт стиснення, трохи швидший, але також важче зрозуміти) ANS )
  2. Якнайбільше інформації про розподіл даних. Принципово важливо, що це не просто "здогадується" про те, як часто може з’являтися одне число, але ви часто можете виключати певні можливості. Наприклад, ви можете виключити інтервали негативного розміру та, можливо, 0 розміру, залежно від того, як визначити допустимий інтервал. Якщо у вас є декілька інтервалів для кодування одразу, ви можете їх сортувати, наприклад, у порядку зменшення ширини або збільшення значення старту / кінця та виключати цілу партію значень (наприклад, якщо ви гарантуєте замовлення за зменшенням ширини, попередній інтервал мала ширину 100, а початкове значення для наступного - 47, потрібно лише врахувати можливості до 147 для кінцевих значень).

Важливо, що число 2 означає, що ви хочете кодувати речі таким чином, щоб найінформативніші значення (за кодом біт) були на першому місці. Наприклад, хоча я пропонував кодувати відсортований список "як є", зазвичай розумніше було б кодувати його як "бінарне дерево" - тобто якщо вони відсортовані за шириною, а у вас є lenелементи, почніть з елемента кодування len/2. Скажіть, вона мала ширину w. Тепер ви знаєте, що всі елементи перед цим мають ширину десь у [0, w], а всі елементи після нього мають ширину десь у [w, max val ви приймаєте]. Повторюйте рекурсивно (підрозділяючи кожен список знову на половину тощо), поки ви не покриєте lenелементи (якщо це не виправлено, вам потрібно буде кодуватиlenпо-перше, так що вам не потрібно турбуватися із закінченням жетонів). Якщо "max val you accept" дійсно відкрито, може бути розумно спочатку кодувати найвище значення, яке насправді з'являється у ваших даних, тобто останній елемент, а потім виконати бінарний розділ. Знову ж таки, що найінформативніше спочатку.

Крім того, якщо ви кодуєте ширину інтервалу спочатку і знаєте максимальне можливе значення, з яким ви маєте справу, очевидно, ви можете виключити всі початкові значення, які зробили б його переповненням ... ви отримуєте ідею. Перетворіть і упорядкуйте свої дані таким чином, щоб ви могли максимально зробити висновок про решту даних під час їх декодування, а оптимальний алгоритм кодування ентропії переконається, що ви не витрачаєте біти на кодування інформації, яку ви "вже знаєте" .

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.