Биты и байты: как машина кодирует числа
JS прячет от тебя машину старательнее любого другого мейнстримного языка: один числовой тип, никаких int и uint, строки сами растут, память сама освобождается. Ровно поэтому у JS-разработчика чаще всего и нет рефлекса видеть за числом биты. А рефлекс нужен: формат бинарного протокола, права доступа в Unix, флаги в чужом API, маски приоритетов внутри React, заголовок страницы в базе данных. Всё это один и тот же навык: прочитать горстку битов глазами.
Этот урок даёт фундамент, на который дальше обопрутся урок про процессор и память, разбор плавающей точки в уроке про типы JS и вся работа с бинарными страницами в воркшопе про свою СУБД.
Карта урока
- Системы счисления: зачем нужны двоичная и шестнадцатеричная, и как они пишутся в JS.
- Бит, байт, машинное слово: единицы измерения данных.
- Целые со знаком: дополнительный код и переполнение.
- Побитовые операторы JS: семь штук, по одному разбору на каждый.
- Битовые маски: проверить, установить, снять, переключить.
- Арифметика сдвигами и пара классических трюков.
Раздел 1 · Системы счисления
Сцена
Открой DevTools и набери (255).toString(2). Получишь '11111111'. Теперь
(255).toString(16): получишь 'ff'. Число одно, записей три. Десятичная
запись для людей, двоичная для понимания машины, шестнадцатеричная для
компактного чтения двоичной.
Идея словами
Любая позиционная система устроена одинаково: цифра вносит вклад, равный
самой цифре, умноженной на степень основания. Возьмём 178 в трёх системах:
десятичная: 1*100 + 7*10 + 8*1 = 178
двоичная 10110010: 1*128 + 0*64 + 1*32 + 1*16
+ 0*8 + 0*4 + 1*2 + 0*1 = 178
hex B2: 11*16 + 2*1 = 178
Шестнадцатеричная запись это просто стенография двоичной: одна hex-цифра
кодирует ровно четыре бита (их называют
нибблами),
байт всегда влезает в две цифры: 0x00 до 0xFF. Когда в дампе памяти или
в цвете #ff8800 ты видишь hex, мысленно дели каждую цифру на четыре бита.
В JS все три записи это литералы одного и того же number:
0b10110010 === 178; // true, двоичный литерал
0o262 === 178; // true, восьмеричный
0xb2 === 178; // true, шестнадцатеричный
(178).toString(2); // '10110010', число в строку
parseInt('b2', 16); // 178, строку в число
Number('0xb2'); // 178, понимает префиксы
Степени двойки стоит знать на глаз, они всплывают везде: лимиты типов, размеры страниц, маски.
| Степень | Значение | Где встречается |
|---|---|---|
| 2^8 | 256 | байт, канал цвета, Uint8Array |
| 2^10 | 1024 | KiB |
| 2^16 | 65 536 | порт TCP, code unit UTF-16 |
| 2^31 - 1 | 2 147 483 647 | максимум int32 |
| 2^32 | 4 294 967 296 | диапазон uint32 |
| 2^53 - 1 | 9 007 199 254 740 991 | Number.MAX_SAFE_INTEGER |
Упражнения
Что взять с собой
Hex это сжатая двоичная запись: цифра, четыре бита, байт, две цифры. Десятичная форма для отчётов, двоичная для понимания операций, hex для чтения дампов и цветов.
Раздел 2 · Бит, байт, машинное слово
Идея словами
Бит это ответ на один вопрос да или нет. Байт это восемь битов и минимальная единица, у которой есть адрес в памяти. Запомни следствие: отдельный бит нельзя адресовать, к нему добираются только операциями над байтом. Весь раздел 5 про маски вырастает из этого ограничения.
Машинное слово это порция, которой оперирует процессор: на современных машинах 64 бита. Подробно мы разберём это в следующем уроке, пока хватит таблицы, что сколько занимает:
| Значение | Размер |
|---|---|
| булев флаг в битовой маске | 1 бит |
| символ ASCII в UTF-8 | 1 байт |
| кириллическая буква в UTF-8 | 2 байта |
| code unit UTF-16 (строки JS) | 2 байта |
элемент Int32Array | 4 байта |
| число JS (float64), указатель | 8 байт |
Про единицы измерения: маркетинг считает килобайт как 1000 байт (KB), техника как 1024 (KiB). Файловые менеджеры и спецификации смешивают оба варианта, поэтому когда важно, пиши явно: KiB, MiB, GiB.
Что взять с собой
Байт это минимальный адресуемый кусок памяти, бит внутри байта достаётся только маской. Размеры в голове: символ 1..4 байта, число JS 8 байт.
дальше после входа
Урок целиком открыт всем, кто вошёл. Войди по своему email, чтобы читать дальше.
Вход пока по приглашению. Если хочешь учиться, напиши Vassiliy.