Базовый CS с нуля
Кодирование мира
Ты уже умеешь записывать число в двоичной системе. Теперь посмотри на это: 8-битный
паттерн 01000001 — это 65 в десятичной. Но компьютер отображает этот же паттерн на
экране как букву А. Завтра, в фотографии, те же восемь битов могут быть одним
каналом красного пикселя. На следующей неделе, в аудиофайле, они могут представлять
громкость звука в конкретный момент времени.
Биты не изменились. Изменилась кодировка — согласованное правило, которое говорит «интерпретируй этот паттерн как букву» или «интерпретируй как значение яркости». Без кодировки биты бессмысленны. Кодировка — это вся история целиком.
После этого урока ты сможешь объяснить, что такое кодировка и почему её нужно согласовывать заранее, описать, как ASCII сопоставляет числа символам (включая коды ключевых символов), объяснить на концептуальном уровне, как Unicode/UTF-8 расширяет эту идею, описать, как RGB использует 8 бит на канал для кодирования цвета, и объяснить, как цифровой звук семплирует непрерывный звук как последовательность чисел.
Биты не имеют собственного смысла. Бит — это просто электрическое состояние:
высокое или низкое напряжение, намагниченность или её отсутствие, заряженность или
незаряженность. Аппаратура хранит и перемещает эти состояния, не зная, что они
означают. Смысл привносится извне — программным обеспечением и соглашениями. Две
программы, читающие байт 01000001, могут прийти к совершенно разным выводам: одна
скажет «число 65», другая — «буква A» — и обе будут правы, каждая в рамках своей
кодировки. Никакого противоречия нет, потому что биты сами по себе не имеют мнения.
Это центральная идея урока: кодировка — это общепринятое соглашение, которое приписывает смысл битовому паттерну. Отправитель и получатель должны договориться о кодировке заранее, иначе коммуникация нарушается.
ASCII: первое универсальное соглашение для текста. В начале 1960-х каждый производитель компьютеров использовал свою собственную договорённость для отображения чисел на символы. Обмен файлами между машинами был постоянной головной болью. В 1963 году Американская ассоциация стандартов опубликовала ASCII — American Standard Code for Information Interchange — 7-битную кодировку, которая присваивает конкретное целое число (от 0 до 127) каждой английской букве, цифре, знаку пунктуации и нескольким управляющим кодам (перевод строки, табуляция, забой и т.д.).
Поскольку 7 бит хранят 2⁷ = 128 значений, ASCII охватывает ровно 128 кодовых позиций. Важные числа, которые стоит запомнить: заглавная ‘A’ — 65, заглавная ‘Z’ — 90; строчная ‘a’ — 97, строчная ‘z’ — 122; цифра ‘0’ — 48, ‘9’ — 57. Заметь, что заглавные и строчные буквы отличаются ровно на 32 — это не случайность, а намеренное решение, позволяющее переключаться между регистрами, изменив всего один бит.
ASCII хранится в 8-битных байтах, при этом старший бит всегда равен нулю. Текстовый файл, использующий только символы ASCII, — это последовательность байтов в диапазоне 0–127.
Граничные случаи
А как насчёт букв с диакритикой вроде é или ñ, кириллицы, китайских иероглифов или эмодзи? ASCII их не охватывает — в нём всего 128 слотов, и все они отведены под английский язык. Были изобретены десятки несовместимых 8-битных расширений для заполнения верхних 128 слотов, что привело к проблеме «кракозябр»: открой файл с неправильной кодировкой, и каждый не-ASCII-символ превратится в мусор (например, «Garçon» отобразится как «Garçon»). Миру потребовалась единая универсальная кодировка.
Unicode и UTF-8: одна кодировка для всех письменных систем. Unicode — это не кодировка, а стандарт, который присваивает уникальное число (называемое кодовой позицией, или code point, записывается как U+XXXX) каждому символу каждой человеческой письменной системы. По состоянию на 2024 год Unicode определяет более 140 000 кодовых позиций, охватывая 161 письменность, а также эмодзи и исторические символы. ‘A’ — это U+0041 (десятичное 65, то же самое, что в ASCII), ‘Ж’ — U+0416, ’😀’ — U+1F600.
UTF-8 — наиболее распространённый способ хранения кодовых позиций Unicode в байтах. Это кодировка переменной длины: кодовые позиции 0–127 (диапазон ASCII) хранятся как один байт, идентичный ASCII. Кодовые позиции выше 127 занимают 2, 3 или 4 байта. Первый байт многобайтовой последовательности сигнализирует, сколько байтов следует дальше, поэтому декодер всегда знает, где начинается каждый символ. Поскольку весь ASCII-текст является допустимым UTF-8, добавление поддержки UTF-8 обратно совместимо — ни один существующий ASCII-файл не сломается.
Концептуальный прорыв: Unicode разделяет две вещи, которые ASCII объединял — абстрактную личность символа (его кодовая позиция, целое число) и конкретные байты для хранения (кодировка, UTF-8). Одну и ту же кодовую позицию можно хранить в UTF-8, UTF-16 или UTF-32 — разные байты, один и тот же символ.
RGB: кодирование цвета тремя числами. Экран компьютера — это сетка крошечных точек, называемых пикселями. Каждый пиксель излучает свет, смешивая три цветовых компонента: Red (красный), Green (зелёный) и Blue (синий). Интенсивность каждого компонента хранится как число. При 8 битах на канал каждый компонент имеет 2⁸ = 256 уровней (0 означает отсутствие этого цвета, 255 — максимальную интенсивность). Три 8-битных канала вместе дают 24 бита на пиксель.
24 бита могут представить 2²⁴ = 16 777 216 различных цветов — достаточно для фотореалистичных изображений. Чистый красный — (255, 0, 0); чистый зелёный — (0, 255, 0); чистый синий — (0, 0, 255); белый — (255, 255, 255), все каналы на максимуме; чёрный — (0, 0, 0), все каналы на нуле. Цвет, который ты видишь, — это кодировка: три байта, которые схема дисплея интерпретирует как интенсивности света.
Форматы высокого класса используют 10 или 12 бит на канал (это «HDR» в современных дисплеях), давая миллиарды цветов. Форматы низкого класса используют меньше битов и жертвуют плавностью цветов. Принцип остаётся тем же: цвет — это соглашение о том, как интерпретировать числа.
PCM-аудио: кодирование звука как последовательности измерений. Звук — это физическая волна: давление воздуха, которое поднимается и опускается во времени. Чтобы хранить звук в цифровом виде, устройство (микрофон или АЦП — аналого-цифровой преобразователь) семплирует давление воздуха через равные интервалы и записывает каждое измерение как целое число. Этот метод называется PCM (импульсно-кодовая модуляция).
Два параметра определяют качество: частота дискретизации (количество измерений в секунду) и битовая глубина (количество битов каждого измерения). Аудио CD-качества использует 44 100 семплов в секунду (44,1 кГц) и 16 бит на семпл, давая 2¹⁶ = 65 536 возможных уровней амплитуды. Профессиональное аудио часто использует 24 бита (16 миллионов уровней) при 96 кГц.
Ключевая идея та же: эти 16-битные целые числа имеют смысл только если декодер знает, что они представляют амплитуды давления воздуха, измеренные с частотой 44,1 кГц. Сохрани те же целые числа в текстовом файле — и текстовый редактор покажет мусорные символы, потому что применит неверную кодировку.
Почему это работает
Почему кодировки должны быть согласованы заранее? Потому что битовые паттерны не несут
никакого самоописывающего ярлыка. Байт 01000001 не может сказать «я — буква».
Отправитель и получатель должны иметь предварительное соглашение — протокол, заголовок
формата файла, MIME-тип, расширение файла — которое называет кодировку. Без этого
соглашения получатель гадает. Иногда угадывает (байты в диапазоне ASCII в текстовом
файле, скорее всего, текст). Часто ошибается, что приводит к кракозябрам, повреждению
изображений или искажению звука.
Декодирование одних и тех же трёх байтов тремя разными способами.
Байты: 01000001 01000010 01000011
Как десятичные числа: 65, 66, 67.
Как текст ASCII: ‘A’, ‘B’, ‘C’ (потому что A=65, B=66, C=67).
Как цвет RGB: красный=65 (тёмно-красный), зелёный=66 (тёмно-зелёный), синий=67 (тёмно-синий) — очень тёмный, почти чёрный цвет с равными долями каждого канала, с небольшим уклоном в синеву. (RGB 65, 66, 67 — тёмно-серый, почти чёрный.)
Все три интерпретации верны. Байты идентичны. Смысл зависит исключительно от кодировки, которую применяет читатель.
Код ASCII для 'A' равен 65. Каков код ASCII для 'C'? (Подсказка: буквы идут подряд в ASCII.)
Сколько битов используется для одного канала цвета RGB (значения 0–255)?
Сколько битов занимает один пиксель RGB (8 бит на канал, 3 канала)?
ASCII использует 7 бит. Сколько различных символов он может закодировать?
Код ASCII для строчной 'a' равен 97. Каков код ASCII для строчной 'z'? (В алфавите 26 букв; 'a' — первая.)
Ты открываешь файл и видишь кракозябры вроде 'Garçon' вместо 'Garçon'. Какова наиболее вероятная причина?
Биты не имеют собственного смысла — это просто паттерны нулей и единиц. Кодировка — это общепринятое соглашение, которое приписывает смысл этим паттернам. ASCII использует 7 бит для отображения 128 кодовых позиций на символы английского языка (‘A’=65, ‘a’=97, ‘0’=48). Unicode распространяет идею на все письменные системы, присваивая каждому символу уникальную кодовую позицию; UTF-8 хранит эти кодовые позиции в 1–4 байтах с обратной совместимостью с ASCII. RGB-цвет использует 3 канала по 8 бит каждый (0–255), давая 16 777 216 возможных цветов на пиксель. PCM-аудио семплирует давление звука через равные интервалы (например, 44 100 раз в секунду) и хранит каждый семпл как целое число фиксированной ширины. Одна и та же последовательность байтов является числом, буквой, цветом или звуком — в зависимости только от того, какую кодировку применяет читатель; без этого соглашения коммуникация разрушается.