Кодування / декодування Base62

Перетворюйте число або рядок байтів за допомогою Base62: 62 символи з цифр, великих літер і малих літер, жоден з яких не потребує екранування в рядку запиту URL чи в тексті HTML. Тому так записують короткі посилання та автоінкрементні ідентифікатори. Два режими: десяткове число (ідентифікатор стає коротким кодом) і байти (текст або шістнадцятковий вхід). Також: Base64 | Base32 / Base58 | Base91.
Уся обробка відбувається локально у вашому браузері — ваші дані ніколи не завантажуються на жоден сервер.

Ніколи не чули про Base62? Що таке Base62 — пояснено простою мовою (з розібраними прикладами, трьома алфавітами та пастками).
Алфавіт:
Доповнити результат до фіксованої ширини: 0 = без доповнення. Доповнення повторює нульовий символ обраного алфавіту, тож те саме число доповнюється по-різному в алфавіті з літерами спочатку.
Як це працює:
Вхідні дані:
Як це працює:
Вивід як:
Ctrl+Enter у полі введення запускає активний режим.
Оберіть «Кодувати» або «Декодувати» та натисніть кнопку дії. Кнопка «Самоперевірка» запускає кожен задокументований приклад, кожну довжину від 0 до 64 байтів і діапазон десяткових чисел через усі три алфавіти, а кількість результатів виводить тут.
Три алфавіти, надруковані повністю: за Base62 немає органу стандартизації, тож алфавіт не гарантований між реалізаціями. Це три порядки, які справді зустрічаються в природі; кожен надруковано символ за символом із його значенням, тож будь-який результат можна простежити до точного алфавіту, що його створив. Затінена клітинка — символ, що означає нуль; він не однаковий у всіх трьох.
Base62 чутливий до регістру в кожному з трьох порядків: велика літера і її мала форма майже завжди означають різні значення, тож код, що пройшов крок переведення в нижній регістр, — це інше число, а не помилка.
Base62 чутливий до регістру в кожному з трьох порядків: велика літера і її мала форма майже завжди означають різні значення, тож код, що пройшов крок переведення в нижній регістр, — це інше число, а не помилка.
Довжина тих самих байтів у кожному кодуванні:
Який розмір вхідних даних приймає ця сторінка і чому: кожен режим тут конвертує через одне велике ціле число, а конвертація великого цілого займає час, пропорційний квадрату довжини. Це властивість самого формату, а не цієї сторінки: будь-який інструмент, що реалізує справжній Base62, має такий самий тип межі. Числа нижче — з тайминг-обв'язки, яка виконує власні процедури сторінки, а не запущену вкладку, тож вони свідомо песимістичні: настільний браузер зазвичай закінчує в кілька разів швидше, і цей запас покриває повільний телефон. Межі вибрано так, щоб навіть повільний випадок завершувався, а не замерзав вкладку.
Понад м'якою межею перший клік пояснює ціну і просить другий клік, перш ніж запуститися; понад жорсткою межею сторінка відмовляється, а не замерзає на кілька секунд без можливості показати прогрес. Байтовий режим рахується в байтах під час кодування і в символах під час декодування, і кількість символів завжди більша: 2048 байтів друкуються як приблизно 2751 символ, що вже за межею символів, тож навантаження приблизно до 1520 байтів — те, що переживає цикл на цій сторінці. Для звичайних бінарних даних будь-якого реального розміру Base64 і Base91 лінійні й такої межі не мають.
Що таке Base62?

Base62 — це спосіб записати число лише символами, які витримують вставку будь-куди: десять цифр, 26 великих літер і 26 малих літер. Жодної пунктуації, пробілів, символу доповнення, нічого, що треба екранувати перед вставкою в URL, назву файлу, cookie чи ключ бази даних. Десять плюс 26 плюс 26 — це 62, звідси назва.

Версія на 30 секунд: число 12345 записується як 3D7, а 1234567890 — як 1LY7VK. Зворотний шлях — та сама операція навпаки, і потрібен точний алфавіт, яким створено код; інший алфавіт перетворить ті самі шість символів на інше число без жодного повідомлення про помилку.

Ця сторінка виконує дві пов'язані задачі, і різниця між ними важливіша за все інше на сторінці:

  • Режим цілих чисел трактує вхідні дані як число. Десятковий ідентифікатор на кшталт 1234567890 стає 1LY7VK, а провідні нулі вхідних даних не є частиною значення, тож вони не повертаються.
  • Байтовий режим трактує вхідні дані як рядок байтів. Байти читаються як одне величезне цілое число з порядком big-endian, а потім діляться на 62 — та сама арифметика, але для іншої величини. Тут кількість провідних нульових байтів зберігається: один нульовий байт на один нульовий символ.
Звідки беруться 62 і що це коштує

62 — не степінь двійки, і цей єдиний факт визначає все інше. Звичні кодування будуються нарізанням вхідних даних на фіксовані групи біт: 4 біти друкуються як один шістнадцятковий символ, 6 біт — як один символ Base64, 5 біт — як один символ Base32. Base62 так не може, бо жодна ціла кількість біт не вкладається в символ із 62 значеннями — 5 біт називають лише 32 значення, 6 біт — 64. Тому Base62 йде через арифметику: прочитати весь вхід як одне ціле число і друкувати його в основі 62.

Тоді один символ несе log2(62) = 5,954 біта, що дуже близько до 6 у Base64, а в десятковому режимі один символ замінює log62(10) = 1,792 десяткових цифри. Кілька наслідків, які варто знати, перш ніж обирати довжину:

Довжина кодуЗначення, які він може назватиНа практиці
4 символи624 = 14 776 336Достатньо для лічильника, що лишається під вісьмома цифрами, і вміщується в простір номера телефону.
6 символів626 = 56 800 235 584Звична форма коду ідентифікатора. Десятковий ідентифікатор з десяти цифр вміщується в шість символів.
7 символів627 = 3 521 614 606 208За межами діапазону 32-бітного лічильника на два порядки, у ширині короткого слага посилання.
11 символів6211 = 52 036 560 683 837 093 888Більше ніж 264 = 18 446 744 073 709 551 616, тож повне 64-бітне число вміщується в одинадцять символів.

Якщо йти у зворотному напрямку, 1000 десяткових цифр потребують близько 558 символів, а 4096 десяткових цифр — 2285. Економія реальна, але обмежена: Base62 скорочує десяткове число приблизно на 44%, і ніколи не перевершує найщільніші друковані кодування, бо 5,954 біта на символ просто менше за 6,4 чи 6,5.

Режим цілих чисел: що відбувається з провідними нулями

Ціле число має одну канонічну письмову форму, і вона починається з нульового символу алфавіту — 0 в двох порядках із цифрами спочатку і A в порядку з літерами спочатку. Усе ліворуч від першого значущого символу — доповнення, а доповнення не є частиною значення: 00012345 і 12345 обидва стають 3D7. Якщо потрібна фіксована ширина — наприклад, семисимвольний код, що має вирівнюватися в колонці, — поле сторінки Доповнити результат до фіксованої ширини повторює нульові символи, доки не досягне ширини, тож 12345 при ширині 7 друкується як 00003D7 в алфавіті цифр-спочатку і як AAAADNH в алфавіті літер-спочатку. Доповнення — косметичне: ці провідні символи нічого не додають до значення, і декодування будь-якого рядка повертає 12345, бо 0 × 626 і 0 × 625 — обидва нулі, незалежно від того, який символ позначає нуль.

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

Байтовий режим: та сама арифметика для рядка байтів

Байтовий режим читає вхідні байти як одне велике ціле число з порядком big-endian — весь рядок байтів трактується як одне число, якою б довгою він не був — і друкує це число в основі 62. Оскільки байт містить 8 біт, а символ називає 5,954 з них, байтовий режим не є стисненням: він потребує приблизно 134% розміру вхідних даних, трохи гірше за 133% у Base64. Для 92-байтового прикладу з таблиці розмірів вище 92 байти друкуються як 124 символи Base62, а Base64 також дає 124 (123 з них до свого доповнення =). Base62 програє Base64 за щільністю і перемагає за безпечністю символів — це компроміс, який кожне коротке посилання і код запрошення робить свідомо.

Провідні нульові байти зберігаються, і в обидва боки це легко зіпсувати. Два провідні нульові байти, за якими йде 0x01, друкуються як 001 в алфавіті цифр-спочатку і як AAB в алфавіті літер-спочатку, бо провідні символи — нулі, по одному на нульовий байт. Рядок байтів із одного 0x00 друкується як один символ 0, а рядок з одного 0x01 — як 1. Це єдине місце, де байтовий режим і режим цілих чисел виглядають по-різному, хоча працюють за одним алгоритмом.

Ціна всього цього в тому, що байтовий режим успадковує квадратичний час арифметики: 1024 байти оцінюються приблизно у третину секунди, а 2048 байтів — приблизно в 1,3 секунди; ті самі цифри дає таблиця лімітів вище. Тому байтовий режим тут обмежено 2048 байтами на виході та 2048 символами на вході — 2048 байтів друкуються як приблизно 2751 символ, тож близько 1520 байтів — найбільше навантаження, яке переживає цикл через цю сторінку, — і тому байтовий режим тут є довідником для малих значень, а не заміною Base64 чи Base91 для реальних файлів.

Три алфавіти і чому сам алфавіт — це вся історія

Символи алфавіту — це фіксована послідовність, а значення символу — його позиція в цій послідовності. Переставлення послідовності змінює значення кожного символу. Використовуються три порядки, і це одне й те саме число, записане трьома способами в кожному з них:

Десяткове0-9, потім A-Z, потім a-z0-9, потім a-z, потім A-ZA-Z, потім a-z, потім 0-9
000A
61zZ9
621010BA
12 3453D73d7DNH
1 234 567 8901LY7VK1ly7vkBViHfU

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

КодЧитається як 0-9 A-Z a-zЧитається як 0-9 a-z A-ZЧитається як A-Z a-z 0-9
3D712 34513 957211 665
1LY7VK1 234 567 8901 624 950 79248 723 527 772

Регістр — друга, гостріша версія тієї самої пастки. Base62 чутливий до регістру в кожному порядку, тож переведення коду в нижній регістр мовчки переписує його: 1LY7VK — це 1 234 567 890 в алфавіті цифр-спочатку, тоді як 1ly7vk у тому самому алфавіті — 1 624 950 792 — і це випадково 1 234 567 890 в алфавіті цифри-потім-малі, бо цей порядок — саме порядок цифри-спочатку з поміняними місцями регістрами літер. Нульовий символ теж не спільний: два порядки з цифрами спочатку записують нуль як 0, тоді як порядок із літерами спочатку записує його як A, тож цей алфавіт узагалі не починається з цифри.

Base62 поруч з іншими кодуваннями
КодуванняБіт на символРозмір відносно вхідних данихПримітки
Base16 (hex)4200%Два символи на байт, легко читається, без алфавіту для пошуку.
Base325160%Нечутливий до регістру і безпечний для диктування вголос, найбільш марнотратний у групі.
Base36 (0-9 a-z)~5,17~155%Лише цифри і малі літери, тож переживає перетворення в нижній регістр. 12345 — це 9ix.
Base58~5,86~137%Обраний для адрес, а не для щільності: чотири схожі символи відкидаються замість упорядкування. Див. Base32 / Base58.
Base62~5,95~134%Кожен символ — цифра або літера, тож ніщо ніколи не екранується. Щільність між Base58 і Base64.
Base646133%Стандарт всюди, ціною +, / і = — трьох символів, які вимагають екранування. Див. Конвертер Base64.
Ascii85 / Base856,4125%5 символів на 4 байти, але ділення на 85, а алфавіт потребує лапок. Див. Ascii85.
Base91~6,5~123%Найщільніший з цих, і той, чий вивід найменш безпечно вставляти без екранування. Див. Base91.

Відсотки — асимптотичні витрати, округлені; виміряні кількості символів для одного реального вхідного рядка з 92 байтів є в таблиці розмірів вище на цій сторінці. У режимі цілих чисел порівняння йде в інший бік, бо вхідні дані — десятковий текст, а не байти: там Base62 приблизно на 44% коротший за цифри, які замінює, а Base36 — приблизно на 36% коротший, тому ідентифікаційний код зазвичай робиться у Base62 або Base36, а не у Base58.

Чим Base62 не є
  • Це не стандарт. Немає RFC і немає специфікації. Жоден орган стандартизації ніколи не визначав Base62, тому алфавіт не гарантований і ця сторінка виводить усі три порядки, а не тихо обирає один.
  • Це не шифрування. Це лише зміна основи, і нічого більше. Будь-хто, хто знає алфавіт, повертає його за один прохід; ні ключа, ні солі, ні будь-якої таємності немає.
  • Це не стиснення. Байтовий режим збільшує дані приблизно на третину. Режим цілих чисел лише схожий на стиснення, бо десятковий текст — неефективний спосіб записати число.
  • Це не нечутливе до регістру. Base32 можна перевести в нижній регістр і прочитати назад; Base62 — ні. Код, що проходить через систему, яка нормалізує регістр, пошкоджений.
  • Це не самоперевірочне. Немає контрольної суми і немає контрольного символу, тож один невірний символ дає правдоподібний результат з іншим значенням. Якщо це важливо, порядок Bitcoin має контрольну суму — див. розділ Base58Check на сторінці Base32 / Base58.
  • Довжина не фіксована. Кількість символів зростає разом зі значенням, тож лічильник, що починається з 1 і доходить до 627, переходить від одного символу до восьми. Доповнюйте до фіксованої ширини, коли потрібна стабільна колонка.
Пастки, які справді кусають
  • Алфавіт — відповідь на дев'ять із десяти загадок. Якщо інший інструмент дає інший код для того самого числа, порівняйте два алфавіти символ за символом, перш ніж підозрювати помилку. Таблиця вище показує те саме значення в трьох алфавітах, і всі три правильні.
  • Неправильний алфавіт відмовляє мовчки. Для нього немає шляху помилки: 3D7 декодується в 12 345, 13 957 або 211 665 залежно лише від того, який порядок припущено. Перевірте перший символ, бо він найімовірніше є нульовим доповненням, і перевірте, чи на початку алфавіту стоять цифри, чи літери.
  • Провідні нулі означають дві різні речі. У режимі цілих чисел 00012345 і 12345 — одне й те саме число і друкуються однаково. У байтовому режимі провідний нульовий байт — це дані, і він друкується як один зайвий нульовий символ. Видалення одного з таких символів змінює рядок байтів.
  • Нормалізація регістру знищує код. Адреса електронної пошти, ім'я хоста чи шлях Windows можуть перетворитися на нижній регістр під час передачі. Код Base62 цього не витримає, і саме тому досі існує Base36.
  • Довгі вхідні дані повільні, а не лише великі. Перетворення — це арифметика над усім вхідним рядком одразу, тож подвоєння довжини вчетверо збільшує час. Ця сторінка відмовляється від вхідних даних за межами виміряних лімітів замість зависання; таблиця розмірів вище містить виміряні цифри.
  • Рядок Base62 — не доказ чогось. Оскільки майже будь-який рядок цифр і літер декодується без скарг, довільний слаг URL декодується в якесь число. Код має значення лише тоді, коли система, що його видала, також зберігає відповідність.
Короткі відповіді

“Чому інший інструмент Base62 дає інший код для того самого числа?”

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

“Чи безпечний Base62 в URL?”

Так, у кожному з трьох порядків. Усі 62 символи — неекрановані літери й цифри, тож жоден із них не розгортається в трійку відсоткових символів у рядку запиту і жоден не закінчує URL, сегмент шляху чи атрибут HTML. Саме тому короткі посилання роблять у Base62, а не в Base64.

“Що менше: Base62 чи Base64?”

Для байтів Base64 трохи менший: приблизно 133% від вхідних даних проти приблизно 134%. На 92-байтовому прикладі вище обидва дають 124 символи. Для десяткових чисел Base62 скорочує текст приблизно на 44% — саме там практична вигода.

“Чи можна декодувати рядок Base64 цією сторінкою?”

Ні, і він не скаже, що провалився. Два алфавіти перетинаються у всіх 62 символах, тож рядок Base64 зазвичай «дійсний» і тут, а просто декодується в інше число. Для Base64 використовуйте Base64.

“Чи має код Base62 максимальну довжину?”

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

“Звідки я знаю, що результат на цій сторінці правильний?”

Натисніть Самоперевірку. Вона запускає кожен задокументований приклад, кожну довжину байтів від 0 до 64 і діапазон десяткових чисел через усі три алфавіти, порівнює повернені значення з тим, що було введено, і знову перевіряє, що всі 62 символи кожного алфавіту безпечні в URL. Кнопка «Приклад» додатково порівнює свої три результати зі значеннями, записаними у файлі даних цієї сторінки, які перевірено проти другої незалежної реалізації з великими цілими числами, що зберігається в тестових інструментах цього сайту.

Стандарти та авторство

Тут немає стандарту для реалізації: Base62 — це конвенція, а не специфікація, і три алфавіти, надруковані вище, — ті, що зустрічаються в реальному програмному забезпеченні. Сторінка реалізує його власними процедурами великих цілих чисел, написаними простою арифметикою над масивами цифр, тож жодний розмір ніколи не обмежується типом числа JavaScript.

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