Руководство разработчика по системам счисления: двоичная, шестнадцатеричная, восьмеричная и десятичная
Полдень, и вы смотрите на 0x7FFF5FBFF8C0 в отладчике, потом переключаетесь в CSS-файл, чтобы поправить #FF5733, а затем выполняете chmod 755 в терминале. Три разных представления числа — одна и та же арифметика под капотом. Если вы хоть раз останавливались, чтобы мысленно перевести между hex и binary, или удивлялись, почему права в Unix вообще в восьмеричной — это руководство сложит для вас эти связи в одну картину.
Мы пройдём по четырём системам счисления, которые встречаются в повседневном программировании, по трём методам конвертации, которые стоит запомнить, и по реальному коду на JavaScript, Python, Go и C. Если хотите пропустить теорию и просто перевести число, откройте наш конвертер систем счисления — он работает с любой базой от 2 до 36 и с произвольной точностью.
Четыре системы счисления, которыми пользуется каждый разработчик
Каждая база живёт в программировании по практической причине, а не по исторической случайности.
Двоичная (база 2) — Язык машины
Две цифры: 0 и 1. Транзистор либо открыт, либо закрыт — это физическое ограничение даёт нам двоичную систему. Вы напрямую столкнётесь с ней при работе с битовыми масками, флагами фич, побитовыми операциями и расчётом IP-подсетей.
Двоичная быстро становится громоздкой. Десятичное 255 — это 11111111 в двоичной: восемь цифр для значения, помещающегося в трёх десятичных. Именно поэтому программисты редко пишут сырые двоичные значения, кроме случаев, когда важны позиции отдельных бит.
Восьмеричная (база 8) — Краткая запись Unix
Восемь цифр: от 0 до 7. Каждая восьмеричная цифра ровно соответствует трём двоичным битам, поэтому права на файлы в Unix — восьмеричные: chmod 755 упаковывает три группы по три бита прав в три читаемых цифры.
У восьмеричной была более крупная роль в эпоху PDP-11, когда машинное слово делилось на 3-битные группы. Сегодня это в основном тема Unix-прав плюс случайный C-литерал с префиксом 0 (который вызвал не один off-by-one баг, когда кто-то написал 0177, ожидая десятичное 177).
Десятичная (база 10) — Человеческий стандарт
Десять цифр: от 0 до 9. Это система, в которой по умолчанию работает ваш мозг — порты, индексы массивов, HTTP-коды, размеры в пикселях. Компьютеры не думают в десятичной, но люди — да, поэтому каждое число, выходящее к пользователю, оказывается в базе 10.
Шестнадцатеричная (база 16) — Швейцарский нож разработчика
Шестнадцать символов: 0-9 и A-F. Каждая hex-цифра представляет ровно четыре двоичных бита (нибл), что делает hex идеально компактным представлением двоичных данных. Две hex-цифры = один байт. Всегда.
Hex встречается в адресах памяти (0x7FFF5FBFF8C0), CSS-цветах (#FF5733), MAC-адресах (00:1A:2B:3C:4D:5E), форматировании UUID и хеш-сумм. Это лингва-франка байтового программирования.
Попробуйте конвертировать между всеми четырьмя системами в нашем конвертере систем счисления — введите значение в любой базе и увидьте, как мгновенно обновляются другие.
Как работает конвертация: три ключевых метода
Чтобы конвертировать между базами, инструмент не нужен, хоть он и ускоряет дело. Три метода покрывают каждый случай.
Метод 1 — Позиционное разложение (любая база → десятичная)
Каждая позиционная система счисления работает одинаково: каждая цифра умножается на базу в степени её позиции, считая справа от нуля.
Двоичное 1011:
1×2³ + 0×2² + 1×2¹ + 1×2⁰
= 8 + 0 + 2 + 1
= 11
Hex FF:
15×16¹ + 15×16⁰
= 240 + 15
= 255
В коде большинство языков делают это через функцию parse:
parseInt('1011', 2) // 11
parseInt('FF', 16) // 255
parseInt('755', 8) // 493
Метод 2 — Повторное деление (десятичная → любая база)
В обратную сторону: делите десятичное число на целевую базу повторно и собирайте остатки. Читайте остатки снизу вверх.
Десятичное 255 → шестнадцатеричное:
255 ÷ 16 = 15 остаток 15 (F)
15 ÷ 16 = 0 остаток 15 (F)
→ Читаем снизу вверх: FF
Десятичное 42 → двоичное:
42 ÷ 2 = 21 остаток 0
21 ÷ 2 = 10 остаток 1
10 ÷ 2 = 5 остаток 0
5 ÷ 2 = 2 остаток 1
2 ÷ 2 = 1 остаток 0
1 ÷ 2 = 0 остаток 1
→ Читаем снизу вверх: 101010
bin(42) # '0b101010'
hex(255) # '0xff'
oct(493) # '0o755'
Метод 3 — Группировка бит (двоичная ↔ hex/octal напрямую)
Этим методом опытные разработчики пользуются чаще всего. Поскольку 16 = 2⁴ и 8 = 2³, можно конвертировать между двоичной и hex (или восьмеричной), просто группируя биты — без арифметики.
Двоичная → Hex: группируем в ниблы (4 бита) справа налево. При необходимости дополняем крайнюю слева группу нулями.
Двоичная: 1010 1111
Hex: A F
→ AF
Двоичная → Octal: группируем в тройки (3 бита) справа налево.
Двоичная: 111 101 101
Octal: 7 5 5
→ 755
Таблицу ниблов стоит запомнить наизусть:
| Двоичное | Hex | Двоичное | Hex |
|---|---|---|---|
0000 | 0 | 1000 | 8 |
0001 | 1 | 1001 | 9 |
0010 | 2 | 1010 | A |
0011 | 3 | 1011 | B |
0100 | 4 | 1100 | C |
0101 | 5 | 1101 | D |
0110 | 6 | 1110 | E |
0111 | 7 | 1111 | F |
Когда эта таблица усвоена, конвертация двоичная → hex становится операцией «взгляд и прочитал».
Конвертация в каждом языке
Вот как обращаться с системами счисления в четырёх языках, где это всплывает чаще всего.
JavaScript / TypeScript
// Парсинг: строка в любой базе → число
parseInt('FF', 16) // 255
parseInt('101010', 2) // 42
parseInt('755', 8) // 493
// Форматирование: число → строка в любой базе
(255).toString(16) // 'ff'
(42).toString(2) // '101010'
(493).toString(8) // '755'
// Литералы
const bin = 0b11111111; // 255
const oct = 0o377; // 255
const hex = 0xff; // 255
// BigInt для значений за пределами 2⁵³
const big = BigInt('0xFFFFFFFFFFFFFFFF');
big.toString(2) // 64 единицы
big.toString(10) // '18446744073709551615'
Python
# Десятичная → другие базы (возвращает строки с префиксом)
bin(255) # '0b11111111'
oct(493) # '0o755'
hex(255) # '0xff'
# Другие базы → десятичная
int('11111111', 2) # 255
int('FF', 16) # 255
int('755', 8) # 493
# Форматированный вывод с padding
f'{255:08b}' # '11111111' (8-значное двоичное, нулевой padding)
f'{255:02x}' # 'ff' (2 цифры hex, нижний регистр)
f'{255:02X}' # 'FF' (2 цифры hex, верхний регистр)
# Целые в Python имеют произвольную точность по умолчанию
big = int('F' * 64, 16) # 256-битное число, без переполнения
Go
package main
import (
"fmt"
"strconv"
)
func main() {
// Форматирование: int → строка в любой базе
fmt.Println(strconv.FormatInt(255, 16)) // "ff"
fmt.Println(strconv.FormatInt(255, 2)) // "11111111"
fmt.Println(strconv.FormatInt(493, 8)) // "755"
// Парсинг: строка в любой базе → int
n, _ := strconv.ParseInt("FF", 16, 64) // 255
fmt.Println(n)
// Глаголы Printf
fmt.Printf("%b %o %x %d\n", 255, 255, 255, 255)
// 11111111 377 ff 255
}
C
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
int main() {
// Вывод в десятичной, восьмеричной, hex
printf("%d %o %x\n", 255, 255, 255);
// 255 377 ff
// Парсинг из любой базы
long val = strtol("FF", NULL, 16); // 255
long bin = strtol("101010", NULL, 2); // 42
// Встроенного binary printf нет — извлекаем вручную:
uint8_t byte = 0xAF;
for (int i = 7; i >= 0; i--)
putchar(((byte >> i) & 1) ? '1' : '0');
// 10101111
return 0;
}
Реальные сценарии конвертации систем счисления
Пять ситуаций, где конвертация перестаёт быть академической и становится частью работы.
1. Отладка адресов памяти
Отладчик показывает указатель 0x7FFF5FBFF8C0. Перевод последних двух байтов в двоичное — 1000 1100 0000 — показывает, что адрес выровнен на границу 64 байт (шесть нулей в конце). Выравнивание важно для производительности кеша, SIMD и memory-mapped I/O. Hex-представление делает эти паттерны видимыми с одного взгляда.
Арифметика указателей тоже легче в hex. Смещение 0x100 от базового адреса — это ровно 256 байт, одна страница во многих встраиваемых системах. В десятичной это не так очевидно.
2. CSS hex-цвета ↔ RGB
Цвет #FF5733 — это три байта, упакованные парами hex:
| Пара | Hex | Десятичное | Канал |
|---|---|---|---|
FF | FF | 255 | Красный (max) |
57 | 57 | 87 | Зелёный |
33 | 33 | 51 | Синий |
Сокращённая запись #F00 разворачивается в #FF0000 — чистый красный. 8-значный вариант #FF573380 добавляет альфа-канал, где 80 (десятичное 128) — около 50% прозрачности.
Знание соответствия hex ↔ десятичная экономит походы в color picker, когда нужно подкрутить канал на конкретное значение.
3. Права файлов Unix (восьмеричная)
chmod 755 разбирается так:
7 → 111 → rwx (владелец: read + write + execute)
5 → 101 → r-x (группа: read + execute)
5 → 101 → r-x (другие: read + execute)
Каждая восьмеричная цифра кодирует ровно одну группу прав, потому что три бита прав (read=4, write=2, execute=1) укладываются в одну восьмеричную цифру (0-7). Типичные паттерны:
| Octal | Двоичное | Права | Типичное использование |
|---|---|---|---|
755 | 111 101 101 | rwxr-xr-x | Исполняемые, директории |
644 | 110 100 100 | rw-r--r-- | Обычные файлы |
700 | 111 000 000 | rwx------ | Приватные скрипты |
600 | 110 000 000 | rw------- | SSH-ключи, секреты |
4. Расчёт сетевых подсетей
Маска подсети /24 означает 24 ведущих единицы в двоичной:
11111111.11111111.11111111.00000000
→ 255.255.255.0
Чтобы найти адрес сети, выполните AND по IP и маске в двоичной:
192.168.1.37 → 11000000.10101000.00000001.00100101
255.255.255.0 → 11111111.11111111.11111111.00000000
AND-результат → 11000000.10101000.00000001.00000000
→ 192.168.1.0 (адрес сети)
Сетевые инженеры регулярно конвертируют между десятичной (запись IP), двоичной (арифметика подсети) и иногда hex (захваты пакетов). Наш конвертер систем счисления обрабатывает каждый октет по отдельности, если хотите визуально сверить.
5. Чтение хеш-сумм и UUID
MD5-хеш вроде d41d8cd98f00b204e9800998ecf8427e — это 32 hex-символа, представляющие 16 байт (128 бит). Каждая пара hex-цифр — один байт.
UUID следует hex-паттерну 8-4-4-4-12:
550e8400-e29b-41d4-a716-446655440000
Это 32 hex-цифры, разделённые дефисами — те же 128 бит, просто отформатированные иначе. Нибл версии стоит на позиции 13 (4 в 41d4 означает UUID v4).
Получайте хеши через наш генератор MD5 и SHA или создавайте UUID через генератор UUID — оба выдают hex-вывод, прямо отображающийся в обсуждаемые двоичные представления.
Помимо базы 16: база 36, база 64 и пользовательские базы
Стандартные четыре базы покрывают большую часть работы, но в специализированных контекстах попадаются и другие.
База 36 — Компактное буквенно-цифровое кодирование
База 36 использует все 10 цифр плюс 26 букв (A-Z), давая самое компактное case-insensitive буквенно-цифровое представление. URL-сокращалки её любят — ID видео YouTube, короткие ссылки и компактные ключи БД часто используют базу 36.
(1000000).toString(36) // 'lfls'
parseInt('lfls', 36) // 1000000
Десятичное 1 000 000 сжимается всего до четырёх символов. Для URL-безопасных коротких идентификаторов это сложно превзойти.
База 64 — Кодирование данных (не система счисления)
Base64 выглядит как ещё одна база, но служит другой цели. Вместо представления числа в позиционной системе Base64 кодирует произвольные двоичные данные (изображения, файлы, JWT-токены) в виде ASCII-текста. Использует A-Z, a-z, 0-9, + и / — всего 64 символа.
Математика отличается от конвертации систем счисления. Base64 обрабатывает вход блоками по 3 байта (24 бита) и выдаёт четыре 6-битных символа. Это схема кодирования, а не система счисления.
Для кодирования и декодирования Base64 используйте наш кодировщик/декодер Base64.
Произвольные базы (2-36) и где они появляются
Несколько других баз встречаются «в дикой природе»:
- База 12 (дюжинная): время (12 часов), количества (дюжина). Часть математиков утверждает, что база 12 удобнее десятичной для повседневного применения, потому что у 12 больше делителей.
- База 60 (шестидесятеричная): время (60 секунд, 60 минут) и углы (360°). Унаследована из вавилонской математики.
- База 32: Crockford Base32 для человекочитаемых идентификаторов (исключает неоднозначные I, L, O). Также применяется в геохешинге.
Наш конвертер систем счисления поддерживает любую целочисленную базу от 2 до 36.
Битовые операции и системы счисления
Понимание двоичной — не только про перевод чисел; это фундамент битовых операций, которые встречаются в системном программировании, разработке игр и системах прав доступа.
const READ = 0b100; // 4
const WRITE = 0b010; // 2
const EXEC = 0b001; // 1
// Объединяем права через OR
const perms = READ | WRITE; // 0b110 = 6
// Проверяем конкретное право через AND
(perms & READ) !== 0 // true — есть read
(perms & EXEC) !== 0 // false — нет exec
// Переключаем право через XOR
perms ^ WRITE // 0b100 = 4 — write убрано
// Сдвиги
1 << 3 // 0b1000 = 8 (1 сдвинут влево на 3)
0xFF >> 4 // 0b00001111 = 15 (сдвиг вправо на 4 = деление на 16)
Флаги фич, аппаратные регистры, сетевые протоколы и графика опираются на битовые операции. Когда двоичная встаёт на место, манипуляции с битами читаются как обычная логика — без всякой магии. Подробный разбор AND, OR, XOR, сдвигов, дополнения до двух и реальных применений вроде feature-флагов и битовых масок — в нашем руководстве по побитовым операциям.
FAQ
Какие четыре основные системы счисления используются в программировании?
Двоичная (база 2), восьмеричная (база 8), десятичная (база 10) и шестнадцатеричная (база 16). Двоичная — это то, как данные физически существуют в железе. Восьмеричная отображается на права файлов Unix. Десятичная — стандарт для общения с человеком. Hex компактно сжимает двоичное в читаемую форму — каждая hex-цифра это ровно 4 бита.
Как перевести двоичное в шестнадцатеричное?
Группируйте двоичные цифры по 4 справа налево, при необходимости дополняя крайнюю слева группу нулями. Сопоставьте каждую группу: 0000=0, 0001=1, …, 1010=A, …, 1111=F. Пример: двоичное 10101111 → группы 1010 1111 → hex AF. Это работает потому, что 16 = 2⁴.
Как перевести шестнадцатеричное в десятичное?
Умножьте каждую hex-цифру на 16 в степени её позиции (крайняя справа = 0) и сложите. A=10, B=11, C=12, D=13, E=14, F=15. Пример: hex FF = 15×16¹ + 15×16⁰ = 240 + 15 = 255. В коде: JavaScript parseInt('FF', 16), Python int('FF', 16).
Почему программисты используют hex вместо двоичного?
Hex компактен. Каждая hex-цифра это ровно 4 бита, поэтому 11111111 00001010 в двоичной становится FF0A в hex — намного короче и проще для чтения. Hex — стандарт для адресов памяти, CSS-цветов (#FF5733), MAC-адресов, хешей и форматирования UUID.
Что такое нибл и почему он важен для перевода в hex?
Нибл — это 4 двоичных бита, половина байта. Один нибл соответствует ровно одной hex-цифре, и именно поэтому конвертация двоичная → hex — это пошаговый поиск по ниблу. Один байт = два нибла = две hex-цифры. Это чистое 4-битное соответствие — причина, по которой hex стал стандартом представления байтовых данных.
Почему права файлов Unix записаны в восьмеричной?
Три бита прав (read=4, write=2, execute=1) на группу, три группы (владелец, группа, другие). Поскольку 2³ = 8, каждая группа из трёх бит укладывается в одну восьмеричную цифру. 755 означает владелец=7 (rwx), группа=5 (r-x), другие=5 (r-x). Восьмеричная — естественная база для 3-битных групп.
Как обрабатывать числа больше 2⁵³ в JavaScript?
Используйте BigInt. Добавьте n к литералу или используйте конструктор BigInt(): BigInt('0xFFFFFFFFFFFFFFFF').toString(2) выдаёт полную 64-битную двоичную строку. Стандартный Number теряет точность за пределами 9 007 199 254 740 991 (2⁵³ - 1). Наш конвертер систем счисления внутри использует BigInt, поэтому работает с числами любого размера без потери точности.
Как перевести шестнадцатеричное в двоичное?
Замените каждую hex-цифру её 4-битным двоичным эквивалентом, используя ту же таблицу ниблов в обратную сторону: 0=0000, 1=0001, …, A=1010, …, F=1111. Пример: hex AF → A (1010) + F (1111) → двоичное 10101111. В коде: JavaScript parseInt('AF', 16).toString(2) или Python bin(int('AF', 16))[2:].
Почему CSS hex-цвета бывают из 3, 6 или 8 цифр?
Все три формы укладываются в RGB-модель, но кодируют разную точность и альфа-канал. 3-значное #F0A — сокращение, разворачивающееся в #FF00AA (каждая цифра удваивается). 6-значное #FF00AA — стандартная RGB-форма: две hex-цифры на канал. 8-значное #FF00AA80 добавляет альфа как четвёртый байт, где 80 (десятичное 128) — около 50% прозрачности. Современные браузеры принимают все три; дизайнеры выбирают самую короткую форму, сохраняющую замысел.