Кодирование информации: что это, виды и способы

Кодирование информации: что это, виды и способы Полезное

Кодирование информации — это перевод данных из одной формы представления в другую по заранее известным правилам, чтобы их было удобно хранить, передавать и обрабатывать. Обратная операция называется декодированием. Ниже разберем, зачем компьютеру двоичный код, какие есть виды и способы кодирования и как на практике кодируются текст, цвет, звук и видео — с примерами на Python, которые можно запустить самому.

Что такое кодирование информации

Любое кодирование опирается на две вещи: набор символов (алфавит) и правило соответствия. Пример из жизни — азбука Морзе, где буквы заменяются точками и тире. Компьютер делает то же самое, только его «алфавит» — всего два состояния.

Важно не путать кодирование и шифрование. При кодировании правило открыто, цель — удобство обработки; при шифровании правило (ключ) скрыто, цель — защита от посторонних. В старых статьях кодирование часто называют «шифрованием» — это неточность.

Код — это набор знаков и правило, по которому одни символы сопоставляются другим. Декодирование — восстановление исходных данных из кода по тому же правилу.

Почему компьютер использует двоичный код

На физическом уровне 0 и 1 кодируются двумя различимыми состояниями схемы. Конкретная реализация зависит от устройства: например, в ячейке динамической памяти DRAM заряд хранит конденсатор, а транзистор управляет доступом к ячейке; в SSD бит — это захваченный заряд в ячейке флеш-памяти; на жестком диске — направление намагниченности участка. Общая идея одна: два состояния надежно отличить друг от друга проще, чем десять, поэтому вся цифровая электроника работает с двумя уровнями сигнала.

Двоичный код — это способ представления информации всего двумя символами, 0 и 1. Любые данные (текст, картинка, звук, видео) в итоге превращаются в последовательность нулей и единиц.

Бит — минимальная единица информации, один разряд двоичного кода со значением 0 или 1. Один бит различает 2 варианта, два бита — 4, три — 8. Общая формула: N бит кодируют 2^N вариантов.

for n in range(1, 5):
    print(n, "бит ->", 2 ** n, "вариантов")

Вывод:

1 бит -> 2 вариантов
2 бит -> 4 вариантов
3 бит -> 8 вариантов
4 бит -> 16 вариантов

Восемь бит образуют байт — 256 вариантов (от 0 до 255). Байт — основная единица, которой оперирует память и файлы.

Виды и способы кодирования: карта уровней

Чтобы не путать «что кодируем» с «как это записано», удобно смотреть на кодирование как на несколько уровней. Любой объект проходит один и тот же путь: от исходной сущности к номеру, затем к байтам и, наконец, к физической записи на носителе.

  • Объект — исходная сущность (буква, точка изображения, мгновенный уровень звука).
  • Абстрактный код — номер объекта по выбранному правилу (кодовая точка, тройка RGB, целое значение уровня). Пока это только число, без привязки к байтам.
  • Байтовое представление — как этот номер укладывается в байты (кодировка текста, число байт на канал цвета, формат аудиоотсчета).
  • Физический носитель — как байты хранит устройство (заряд, намагниченность, ячейка флеш-памяти).

Проведем по этой карте три сквозных объекта — букву, пиксель и аудиоотсчет:

Уровень Буква «Я» Пиксель цвета Аудиоотсчет
Объект символ «Я» одна точка изображения мгновенный уровень сигнала
Абстрактный код кодовая точка U+042F RGB (40, 120, 200) целое число уровня, напр. 15230
Байтовое представление D0 AF (UTF-8) 28 78 C8 (по байту на канал) 7E 3B (16 бит, little-endian)
Физический носитель заряд / намагниченность / ячейка флеш то же то же

Дальше «виды» — это верхняя строка (буква, пиксель, звук), а «способы» — как заполняются средние строки для каждого вида. Разберем их по очереди.

Как кодируется текст: ASCII, Unicode, UTF-8

Здесь важно развести два понятия, которые легко путаются.

Набор символов (character set) отвечает на вопрос «какой номер у символа». Unicode — это именно набор символов: он назначает каждому абстрактному символу кодовую точку (code point), например «Я» получает кодовую точку U+042F. Сам по себе номер не говорит, сколькими байтами его записать.

Кодировка (encoding) отвечает на вопрос «как записать этот номер байтами». UTF-8, UTF-16 — это кодировки: они задают правило перевода кодовой точки в конкретные байты. В UTF-8 кодовая точка U+042F превращается в два байта D0 AF.

Мини-цепочка целиком: символ «Я» -> кодовая точка U+042F (набор символов) -> байты D0 AF (кодировка UTF-8).

Историческая база — ASCII: 7 бит на символ, 128 позиций (латиница, цифры, знаки препинания, управляющие символы). Для кириллицы и других алфавитов места не хватило, поэтому появились 8-битные кодировки на 256 символов: первые 128 совпадают с ASCII, вторые 128 отданы под национальный алфавит (для русского — Windows-1251, KOI8-R, ISO 8859-5).

Проблема 8-битных кодировок: в один текст нельзя одновременно вписать, например, кириллицу и греческий, а при неверной кодировке появляются «кракозябры». Решение — Unicode: единая таблица, где своя кодовая точка есть у символа любого языка, а также у emoji. Unicode — это не размер в байтах, а нумерация: кодовые точки идут до U+10FFFF, всего чуть больше 1,1 млн возможных позиций, из них в версии 17.0 назначено 159 801 символ.

Как записать кодовую точку в байты — решает кодировка представления. Самая распространенная в вебе — UTF-8: одна кодовая точка занимает от 1 до 4 байт. Латиница остается 1 байтом (совместимость с ASCII), кириллица — 2 байта, многие emoji — 4 байта.

Кодировка Размер Сколько символов Что покрывает
ASCII 7 бит 128 латиница, цифры, базовые знаки
Windows-1251 8 бит 256 ASCII + кириллица
Unicode (набор символов) кодовые точки до U+10FFFF 159 801 назначено (v17.0) все письменности + emoji
UTF-8 1-4 байта на кодовую точку весь Unicode ASCII-совместима, стандарт веба
UTF-16 2 или 4 байта весь Unicode строки внутри Windows, Java, JS

Важная оговорка про «символы». Одна кодовая точка — это не всегда один видимый символ. Видимый пользователю символ называют графемой, и он может состоять из нескольких кодовых точек: например, emoji с модификатором тона кожи или семейный emoji склеиваются из нескольких кодовых точек и занимают в UTF-8 больше 4 байт. Функция len(s) в Python считает именно кодовые точки, а не всегда графемы.

Символ Кодовая точка UTF-8 байты len() в Python
A U+0041 41 1
Я U+042F D0 AF 1
U+20AC E2 82 AC 1
😀 U+1F600 F0 9F 98 80 1
👍🏽 U+1F44D U+1F3FD F0 9F 91 8D F0 9F 8F BD 2

Последняя строка — тот самый случай: один видимый значок (палец с тоном кожи) — это две кодовые точки, восемь байт и len() равный 2.

Посмотрим на кодирование текста в Python. Функция ord дает номер (кодовую точку) символа, chr — обратно символ по номеру:

print(ord('A'))            # 65
print(chr(65))             # A
print(ord('Я'))            # 1071, это U+042F

Вывод:

65
A
1071

Теперь превратим строку в байты через UTF-8 и посмотрим, сколько места она занимает:

s = 'Привет'
print(len(s))                   # 6 кодовых точек
print(len(s.encode('utf-8')))   # 12 байт (кириллица по 2 байта)
print(s.encode('utf-8'))

Вывод:

6
12
b'\xd0\x9f\xd1\x80\xd0\xb8\xd0\xb2\xd0\xb5\xd1\x82'

Типичная ошибка: чужая кодировка при декодировании

Байты без указания кодировки — просто числа. Если декодировать их не той таблицей, получится ошибка или мусор. Разберем тройкой.

Неверный код — пытаемся прочитать UTF-8 байты как ASCII:

b = 'Привет'.encode('utf-8')
print(b.decode('ascii'))

Фактический результат — программа падает:

UnicodeDecodeError: 'ascii' codec can't decode byte 0xd0 in position 0: ordinal not in range(128)

ASCII знает только позиции 0-127, а первый байт кириллицы равен 0xd0 (208) — выходит за диапазон. Исправление — декодировать той же кодировкой, которой кодировали:

b = 'Привет'.encode('utf-8')
print(b.decode('utf-8'))   # Привет

Правило простое: кодируй и декодируй одной кодировкой, а при работе с файлами и сетью явно указывай encoding='utf-8'.

Как кодируются числа

Целые числа переводятся в двоичную систему счисления напрямую. Функция bin в Python показывает двоичную запись:

print(bin(5))    # 0b101
print(bin(255))  # 0b11111111
print(0b101)     # 5

Вывод:

0b101
0b11111111
5

Отрицательные числа — отдельная тема. В регистрах процессора и типах фиксированной ширины (например, int32 в C или Java) их обычно хранят в дополнительном коде (two’s complement). В Python тип int — произвольной точности: он не занимает фиксированное число бит, а битовые операции определены так, будто число записано в дополнительном коде с бесконечным числом знаковых разрядов. Поэтому bin(-5) показывает не «настоящие биты в памяти», а знак и модуль. Увидеть дополнительный код в конкретной ширине можно маской:

print(bin(-5))         # -0b101 (знак и модуль)
print(bin(-5 & 0xFF))  # 0b11111011 - дополнительный код в 8 битах

Вывод:

-0b101
0b11111011

Дробные числа хранят в формате с плавающей точкой (IEEE 754). Из-за конечного числа битов дроби хранятся приближенно — отсюда классический 0.1 + 0.2, дающий не ровно 0.3. Это не ошибка Python, а свойство двоичного представления дробей.

Как кодируются цвет и графика

Растровое изображение делится на пиксели — мелкие точки. Цвет каждого пикселя задают моделью RGB: три числа — доли красного, зеленого и синего. Обычно на каждый канал отводится 8 бит (0-255), значит на пиксель — 24 бита, а всего оттенков 256^3, это около 16,7 млн.

Глубина цвета — это число бит на пиксель: чем больше, тем больше оттенков. Разрешение (число пикселей) влияет на детализацию: камера на 12 мегапикселей раскладывает кадр примерно на 12 млн точек.

Векторная графика устроена иначе: вместо сетки пикселей хранятся описания фигур — линий, кривых, окружностей с их параметрами (координаты, толщина, цвет заливки). Такую картинку можно масштабировать без потери качества. Для фотографий обычно эффективнее растр (JPEG, PNG): в них множество несистемных оттенков, которые формулами не описать. Вектор удобнее для геометрических объектов — логотипов, иконок, шрифтов, схем (SVG).

Как кодируются звук и видео

Звук — это колебания воздуха. Микрофон превращает их в электрический сигнал, а звуковая карта измеряет его уровень много раз в секунду — это дискретизация. Частота дискретизации 44100 Гц означает 44100 замеров в секунду; каждый замер (отсчет) округляется до ближайшего уровня из доступных — это квантование. Чем выше частота и разрядность отсчета, тем точнее восстановится звук, но тем больше размер файла.

Видео — это графика плюс звук. Кадры кодируются как растровые изображения, звуковая дорожка — как аудио. Чтобы файл не был огромным, применяют сжатие. Упрощенно это работает так: кодек хранит несколько внутрикодированных (опорных) кадров целиком, а остальные предсказывает по одному или нескольким опорным кадрам, записывая лишь отличия. Это именно упрощенная модель: в реальных кодеках есть разные типы кадров, а предсказание может опираться и на предыдущие, и на будущие кадры.

На этом принципе работают кодеки, например H.264, H.265 и AV1. Стандарты продолжают выходить: Alliance for Open Media опубликовал следующий за AV1 стандарт AV2 (актуальность и уровень поддержки стоит сверять на дату публикации). Поэтому лучше держаться конкретных названий, а не ярлыка «самый новый».

Выводы

  • Кодирование — это перевод данных в другую форму по открытому правилу; декодирование — обратный перевод. Шифрование — другая задача (защита ключом), путать их не нужно.
  • Компьютер работает в двоичном коде, потому что два различимых состояния схемы надежнее десяти; N бит кодируют 2^N вариантов, 8 бит — это байт и 256 значений.
  • Удобно думать уровнями: объект -> абстрактный код (номер) -> байты -> физический носитель. «Виды» — это разные объекты (буква, пиксель, звук), «способы» — как заполняются средние уровни.
  • В тексте различают набор символов (Unicode назначает кодовые точки) и кодировку (UTF-8/UTF-16 пишут кодовые точки байтами); главная причина «кракозябр» — декодирование не той кодировкой.
  • Один видимый символ (графема) может состоять из нескольких кодовых точек, поэтому число символов, кодовых точек и байт в строке часто не совпадает.

Где применяется / связь с практикой

Понимание кодировок нужно каждый день: прочитать CSV без «кракозябр», не сломать текст при выгрузке из базы, корректно принять JSON от чужого API, разобраться, почему длина строки в символах и в байтах разная. Как только вы начинаете писать код, работать с файлами и сетью, кодировки перестают быть теорией.

Освойте тему на практике

Разобраться с этим удобно на Python: в нем строки и байты — разные типы, а методы encode и decode наглядно показывают, что происходит с данными. Собрать базу с нуля помогает курс Python Basic — там же на практике разбирают работу с текстом и файлами. Если хочется сначала присмотреться к формату и направлению, посмотрите ближайшие бесплатные вебинары и вживую задайте вопросы преподавателям.

Смежные темы: Кодирование символов и UTF, Введение в кодирование информации, Кодирование и декодирование: что должен знать программист.

FAQ

Чем кодирование отличается от системы счисления? Система счисления (двоичная, десятичная) — это способ записать число. Кодирование шире: оно сопоставляет по правилу любые данные, в том числе не-числовые, а уже их номера записываются в какой-то системе счисления.

Почему один и тот же файл открывается «кракозябрами» в одной программе и нормально в другой? Программы по умолчанию предполагают разные кодировки. Если текст сохранен в UTF-8, а редактор читает его как Windows-1251 (или наоборот), символы декодируются не теми таблицами. Нужно явно выбрать правильную кодировку при открытии.

Почему len() строки с emoji бывает больше, чем видно символов? Потому что len() считает кодовые точки, а один видимый значок (графема) — например, emoji с тоном кожи или семейный emoji — собран из нескольких кодовых точек. В UTF-8 такой символ занимает и больше 4 байт.

OTUS Журнал
Скидка 10% 7-13 сентября на курсы из спецкаталога (pop-up)