Система счисления — это способ записывать числа набором цифр по согласованным правилам. От выбранной системы зависит, какими знаками пишут число и как по записи восстановить его величину. Привычная нам десятичная — лишь одна из многих.
Содержание
- Позиционные и непозиционные системы
- Основание и разряд: как устроена позиционная запись
- Четыре системы, которые встречаются в IT
- Как перевести число в десятичную систему
- Как перевести десятичное число в другую систему
- Встроенные средства Python
- Двоичная, восьмеричная и шестнадцатеричная: перевод без деления
- Выводы
- Где применяется и что учить дальше
- FAQ
Ниже разберем, чем позиционная система отличается от непозиционной, как устроены двоичная, восьмеричная и шестнадцатеричная системы и почему именно они прижились в вычислительной технике. Главное — научимся переводить числа из одной системы в другую руками и на Python. Все примеры кода в статье запущены, вывод под ними реальный.
Позиционные и непозиционные системы
Системы счисления делятся на два класса по тому, влияет ли позиция цифры на ее вклад в число.
Непозиционная система — значение цифры не зависит от ее места в записи. Пример — римская: в записи XXX каждый X всегда означает 10, а число получается сложением (XXX = 30). Такие системы наглядны для мелких чисел, но неудобны для арифметики и записи больших величин.
Позиционная система — вклад цифры зависит от ее позиции (разряда). В числе 555 три одинаковые цифры означают разное: пять сотен, пять десятков и пять единиц. Именно позиционные системы используют в математике и технике, потому что в них просто считать по разрядам.
Дальше речь только о позиционных системах — к ним относятся десятичная, двоичная, восьмеричная и шестнадцатеричная.
Основание и разряд: как устроена позиционная запись
У любой позиционной системы есть основание — количество разных цифр в ней. В десятичной основание 10 и цифры 0-9, в двоичной основание 2 и цифры 0 и 1.
Значение числа — это сумма цифр, умноженных на основание в степени номера разряда. Разряды нумеруют справа налево, начиная с нуля. Для десятичного 463 это читается так:
463 = 4*10^2 + 6*10^1 + 3*10^0 = 400 + 60 + 3
Тот же принцип работает в любой системе — меняется только основание. Двоичное число 1011 раскрывается по степеням двойки:
1011 = 1*2^3 + 0*2^2 + 1*2^1 + 1*2^0 = 8 + 0 + 2 + 1 = 11
Эта формула — разложение по степеням основания — и есть ключ к переводу любого числа в десятичную систему.
Четыре системы, которые встречаются в IT
В программировании постоянно попадаются четыре системы. Ниже — что это за системы и зачем каждая нужна.
| Система | Основание | Цифры | Где встречается |
|---|---|---|---|
| Двоичная | 2 | 0, 1 | внутреннее представление данных, биты и флаги, побитовые операции |
| Восьмеричная | 8 | 0-7 | права доступа к файлам в Unix (chmod 755) |
| Десятичная | 10 | 0-9 | обычная запись чисел, ввод и вывод для человека |
| Шестнадцатеричная | 16 | 0-9, A-F | цвета (#ff8800), адреса памяти, байты, хеши |
Компьютер хранит и обрабатывает данные в двоичном виде: у транзистора удобно различать два устойчивых состояния, их и кодируют как 0 и 1. Но длинные цепочки битов человеку читать тяжело, поэтому их сокращают.
Здесь помогают восьмеричная и шестнадцатеричная системы: их основания — степени двойки (8 = 2^3, 16 = 2^4), поэтому группы битов переводятся в их цифры без арифметики. Одна шестнадцатеричная цифра заменяет ровно четыре бита — об этом ниже отдельный раздел.
В шестнадцатеричной не хватает обычных цифр, поэтому значения 10-15 записывают буквами A-F: A = 10, B = 11, C = 12, D = 13, E = 14, F = 15. Регистр букв роли не играет.
Как перевести число в десятичную систему
Перевод в десятичную — это прямое применение разложения по степеням основания. Берем каждую цифру, умножаем на основание в степени ее разряда и складываем.
Разберем шестнадцатеричное 2BC. Разряды справа налево: C (разряд 0), B (разряд 1), 2 (разряд 2). Подставляем значения букв (C = 12, B = 11):
2BC = 2*16^2 + 11*16^1 + 12*16^0 = 512 + 176 + 12 = 700
В коде удобнее не считать степени вручную, а идти по цифрам слева направо, каждый раз домножая накопленное на основание. Это классическая схема Горнера:
def to_decimal(text, base):
digits = "0123456789ABCDEF"
value = 0
for ch in text.upper():
value = value * base + digits.index(ch) # сдвигаем разряд и добавляем цифру
return value
print("10011100 (2) ->", to_decimal("10011100", 2))
print("234 (8) ->", to_decimal("234", 8))
print("2BC (16) ->", to_decimal("2BC", 16))
Вывод программы:
10011100 (2) -> 156
234 (8) -> 156
2BC (16) -> 700
Первые два числа неспроста дали одинаковый результат: 10011100 в двоичной, 234 в восьмеричной и 156 в десятичной — это одна и та же величина, записанная по-разному.
Как перевести десятичное число в другую систему
Обратный перевод делают делением с остатком. Число многократно делят на основание целочисленно, а остатки от деления и есть цифры новой записи — но их собирают снизу вверх, от последнего к первому.
Переведем 156 в двоичную. Делим на 2, пока не дойдем до нуля, и выписываем остатки:
156 : 2 = 78, остаток 0
78 : 2 = 39, остаток 0
39 : 2 = 19, остаток 1
19 : 2 = 9, остаток 1
9 : 2 = 4, остаток 1
4 : 2 = 2, остаток 0
2 : 2 = 1, остаток 0
1 : 2 = 0, остаток 1
Читаем остатки снизу вверх: 10011100. Тот же алгоритм в коде — для любого основания до 16:
def from_decimal(n, base):
if n == 0:
return "0"
digits = "0123456789ABCDEF"
out = ""
while n > 0:
out = digits[n % base] + out # остаток - очередной разряд, дописываем слева
n //= base # целочисленное деление сдвигает число
return out
for base in (2, 8, 16):
print(f"156 в основании {base}:", from_decimal(156, base))
Вывод программы:
156 в основании 2: 10011100
156 в основании 8: 234
156 в основании 16: 9C
Оговорка о границе: функция работает с неотрицательными целыми и основаниями до 16 (цифр в строке digits ровно 16). Для оснований больше 16 нужен более длинный алфавит цифр, а для отрицательных чисел — отдельная обработка знака.
Встроенные средства Python
Свои функции полезны, чтобы понять механику, но в реальном коде переводы уже встроены в язык. Python переводит десятичное число в строку другой системы функциями bin, oct, hex, а обратно — функцией int со вторым аргументом-основанием.
n = 156
print("bin:", bin(n)) # префикс 0b - двоичная
print("oct:", oct(n)) # префикс 0o - восьмеричная
print("hex:", hex(n)) # префикс 0x - шестнадцатеричная
# обратно: строка записи + основание -> десятичное число
print(int("10011100", 2))
print(int("234", 8))
print(int("9c", 16))
Вывод программы:
bin: 0b10011100
oct: 0o234
hex: 0x9c
156
156
156
Префиксы 0b, 0o, 0x — это не часть числа, а пометка системы счисления. Их же можно писать прямо в исходном коде: 0b10011100, 0o234 и 0x9c — три способа записать одну константу 156, и Python хранит их одинаково.
Двоичная, восьмеричная и шестнадцатеричная: перевод без деления
Между двоичной и двумя другими системами перевод идет быстрее, чем через десятичную, потому что 8 и 16 — степени двойки. Одна восьмеричная цифра — это ровно 3 бита, одна шестнадцатеричная — ровно 4 бита.
Правило простое: разбиваем двоичную запись на группы (по 4 бита для hex, по 3 для oct), считая справа, и каждую группу заменяем одной цифрой. Если слева группа неполная, дополняем ее нулями. Проверим это кодом:
n = 0b1010111100 # двоичное число, записанное прямо в коде
print("hex:", hex(n))
print("oct:", oct(n))
bits = "1010111100"
pad = (-len(bits)) % 4 # сколько нулей добить слева до кратности 4
bits4 = "0" * pad + bits
groups = [bits4[i:i+4] for i in range(0, len(bits4), 4)]
hex_digits = "".join("0123456789abcdef"[int(g, 2)] for g in groups)
print("группы по 4 бита:", groups, "->", hex_digits)
Вывод программы:
hex: 0x2bc
oct: 0o1274
группы по 4 бита: ['0010', '1011', '1100'] -> 2bc
Группировка вручную дала тот же результат 2bc, что и встроенный hex. Именно поэтому шестнадцатеричная запись так удобна для байтов: один байт (8 бит) — это всегда ровно две hex-цифры, от 00 до ff.
Выводы
- Система счисления — это правило записи чисел цифрами; позиционные (значение зависит от разряда) вытеснили непозиционные в математике и технике.
- В IT главные системы — двоичная (данные в компьютере), шестнадцатеричная и восьмеричная (компактная запись битов), десятичная (ввод-вывод для человека).
- Перевод в десятичную — разложение по степеням основания; из десятичной — деление с остатком, остатки читаются снизу вверх.
- Восьмеричная и шестнадцатеричная переводятся из двоичной группами по 3 и 4 бита без арифметики, потому что 8 и 16 — степени двойки.
- В Python переводы встроены:
bin,oct,hexиз числа в строку иint(s, base)обратно.
Где применяется и что учить дальше
Системы счисления — это фундамент, на который опирается почти все в программировании: побитовые операции и маски, цвета в вебе (#ff8800), права доступа chmod 755, чтение дампов памяти и адресов, разбор сетевых пакетов и хешей. Понимание переводов помогает не заучивать, а видеть, что за компактной hex-записью стоят обычные биты.
Освойте тему на практике
Если хочется освоить это на практике — писать функции перевода, работать с числами и строками, разбирать побитовые операции — посмотрите курс Python Basic. Оценить формат и уровень до старта помогают бесплатные открытые уроки Otus — живые занятия с преподавателями.
Смежные темы: Двоичная система счисления.
FAQ
Почему в компьютерах используют именно двоичную систему? Электронной схеме проще надежно различать два состояния (есть сигнал или нет), чем десять уровней. Два состояния кодируют как 0 и 1, поэтому вся обработка данных идет в двоичном виде.
Зачем нужна шестнадцатеричная, если есть двоичная? Двоичная запись длинная и в ней легко ошибиться при чтении. Шестнадцатеричная короче в четыре раза и переводится в биты без вычислений, поэтому ей удобно записывать байты, цвета и адреса.
Что означают буквы A-F в шестнадцатеричном числе? Это цифры от 10 до 15, которым не хватило обычных знаков: A = 10, B = 11, C = 12, D = 13, E = 14, F = 15. Регистр не важен, 9c и 9C — одно и то же.



