ЕГЭ, ОГЭ, программирование и робототехника в Калининграде

Системы счисления

Исторические системы счисления

Потребность в подсчёте возникла у человечества задолго до появления письменности. Первые системы счисления формировались естественным образом – люди использовали пальцы рук для счёта, что впоследствии определило доминирование десятичной системы в большинстве культур. Однако путь развития математической записи чисел оказался удивительно разнообразным.

Древний Египет: иероглифическая арифметика

Египетская цивилизация создала одну из первых документированных систем счисления около 3000 года до н. э. Эта непозиционная система использовала специальные иероглифы для обозначения степеней десяти:

  • Вертикальная черта обозначала единицу
  • Путы для скота символизировали десяток
  • Свёрнутая верёвка представляла сотню
  • Цветок лотоса означал тысячу
  • Указательный палец – десять тысяч
  • Головастик – сто тысяч
  • Человек с поднятыми руками – миллион

Для записи числа египтяне просто повторяли нужные символы необходимое количество раз. Несмотря на громоздкость при записи больших чисел, эта система позволяла египетским писцам вести сложный учёт в строительстве пирамид и управлении государством.

Вавилон: революция основания 60

Вавилонская шестидесятеричная система, возникшая около 2000 года до н. э., стала одним из величайших математических достижений древности. В отличие от египетской, она была позиционной – значение символа зависело от его места в записи числа.

Выбор основания 60 не был случайным. Это число имеет двенадцать делителей (1, 2, 3, 4, 5, 6, 10, 12, 15, 20, 30, 60), что делало вычисления с дробями значительно проще. Вавилонские математики использовали клинописные символы, комбинируя вертикальный клин для единиц и угловой для десятков.

Наследие этой системы живёт в современном мире: 60 секунд в минуте, 60 минут в часе, 360 градусов в окружности – всё это отголоски вавилонской математики. Астрономические расчёты вавилонян были настолько точными, что их методы использовались вплоть до эпохи Возрождения.

Древний Рим: практичность без позиционности

Римская система счисления, появившаяся около 500 года до н.э., отличалась от восточных аналогов своей аддитивно-субтрактивным принципом (сложения и вычитания). Семь основных символов (I, V, X, L, C, D, M) комбинировались по принципу сложения и вычитания:

  • Если меньшая цифра стоит после большей – они складываются (VI = 6)
  • В допустимых сочетаниях меньшая цифра перед большей вычитается (IV = 4)

Эта система прекрасно подходила для записи результатов и ведения учёта, но была крайне неудобна для вычислений. Римские торговцы и инженеры использовали для расчётов абак (фото ниже), а числа записывали уже после получения результата.

Несмотря на ограничения, римская нумерация продержалась в Европе до позднего Средневековья и до сих пор используется для обозначения веков, томов книг и циферблатов часов. Ниже пример использования римских цифр на циферблате часов Спасской башни.

Славянская кириллическая нумерация: буквы становятся числами

С принятием христианства и распространением кириллицы в X–XI веках славянские народы переняли византийскую традицию использования букв алфавита для записи чисел. Эта система, просуществовавшая на Руси до начала XVIII века, отличалась изяществом и компактностью.

Основные принципы славянской нумерации:

  • Первые девять букв кириллицы обозначали единицы (А (аз) = 1, В (веди) = 2, Г (глаголь) = 3)
  • Следующие девять – десятки (І (и) = 10, К (како) = 20, Л (люди) = 30)
  • Далее шли сотни (Р (рцы) = 100, С (слово) = 200, Т (твердо) = 300)

Для отличия чисел от обычного текста над буквами ставился специальный знак – титло ( ҃).

Число записывалось слева направо от больших разрядов к меньшим, но существовало исключение: числа от 11 до 19 записывались с единицами перед десятком, отражая устную традицию (например, «два на десять» для 12 – ВI).

Для больших чисел использовались специальные обозначения:

  • Тысячи отмечались знаком «҂» перед буквой
  • «Тьма» (10 000) обозначалась обведённой кругом буквой
  • «Легион» (100 000) – буквой в кругу из точек
  • и т.д.

Эта система активно использовалась в летописях, церковных книгах, торговых документах и государственных актах. Интересно, что в некоторых математических трактатах того времени встречались вычисления с дробями, где числитель писался над знаменателем без дробной черты.

Переход на арабские цифры в России произошёл при Петре I в рамках общей модернизации, хотя в церковной литературе кириллическая нумерация сохранялась значительно дольше.

Ниже пример использования славянских цифр на кремлёвских часах Суздаля.

Современные системы: от повседневности до микропроцессоров

Ну а со многими современными системами счисления вы уже должны быть знакомы. Вкратце пробежимся по ним.

Десятичная система остаётся основной для человечества. Её универсальность обусловлена анатомией человека и тысячелетними традициями. Большинство финансовых расчётов и повседневная арифметика используют основание 10.

Двоичная система стала фундаментом цифровой эры. Простота представления информации в виде двух состояний (0 и 1) идеально соответствует физической природе транзисторов – основных элементов компьютеров. Каждый бит информации – это выбор между двумя возможностями, что делает двоичную систему незаменимой для цифровой электроники.

Восьмеричная система получила распространение в раннюю компьютерную эпоху как компромисс между компактностью записи и простотой перевода в двоичную форму. Три двоичных разряда точно соответствуют одной восьмеричной цифре, что упрощало работу программистов с машинным кодом. Сегодня она сохраняется в Unix-подобных системах для установки прав доступа к файлам (например, chmod 755).

Шестнадцатеричная система стала стандартом де-факто в программировании. Четыре двоичных разряда образуют одну шестнадцатеричную цифру, что обеспечивает оптимальный баланс между компактностью и читаемостью. Применение обширно:

  • Адресация памяти в отладчиках (0x7FFF5694)
  • Представление цветов в веб-разработке (#FF5733 для RGB)
  • MAC-адреса сетевых устройств (00:1B:44:11:3A:B7)
  • Криптографические хеши и ключи
  • Дампы памяти и анализ бинарных файлов

История систем счисления – это история оптимизации человеческой мысли под конкретные задачи. От подсчёта урожая в Древнем Египте до квантовых вычислений современности, каждая эпоха находила свои решения для представления чисел. В эру искусственного интеллекта и квантовых компьютеров мы, возможно, стоим на пороге создания принципиально новых систем представления информации, которые выйдут за рамки традиционных числовых оснований.

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

Методы перевода чисел между системами счисления

В программировании регулярно возникает необходимость конвертировать числа из одной системы счисления в другую. Будь то отладка кода, работа с цветами или анализ сетевых протоколов – везде требуется умение быстро и точно переводить числа между десятичной, двоичной, восьмеричной и шестнадцатеричной системами.

Универсальный алгоритм деления

Классический метод перевода из десятичной системы в любую другую основан на последовательном делении с фиксацией остатков. Этот алгоритм работает для любого основания от 2 до 36 и является фундаментальным в теории чисел.

При переводе числа из десятичной системы мы последовательно делим его на основание целевой системы, записывая остатки от деления. Эти остатки, прочитанные в обратном порядке, формируют искомое представление числа.

Для примера давайте переведём число 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 – это и будет число 42 в двоичной системе счисления.

Пошаговый алгоритм перевода

Шаг 1: Определение основания целевой системы

Выберите основание N системы счисления, в которую необходимо перевести число. Стандартные основания:

  • 2 для двоичной системы
  • 8 для восьмеричной
  • 16 для шестнадцатеричной
  • Любое число от 2 до 36 для остальных систем

Шаг 2: Последовательное деление

Выполняйте целочисленное деление исходного числа на основание N:

  1. Разделите число на N
  2. Запишите остаток от деления
  3. Результат деления используйте для следующей итерации
  4. Повторяйте, пока частное не станет равным нулю

Шаг 3: Формирование результата

Остатки от деления, записанные в обратном порядке (от последнего к первому), образуют число в новой системе счисления.

Шаг 4: Обработка оснований больше 10

Для систем счисления с основанием больше 10 используется расширенный набор символов:

  • Цифры 0-9 для значений от 0 до 9
  • Буквы A-Z для значений от 10 до 35

Теперь по этому алгоритму переведём число 78 в восьмеричную систему счисления:

  • 78 ÷ 8 = 9 (остаток 6)
  • 9 ÷ 8 = 1 (остаток 1)
  • 1 ÷ 8 = 0 (остаток 1)

Получилось число 116.

Оптимизация для степеней двойки

Особый случай представляют системы счисления, основание которых является степенью двойки (4, 8, 16). Для них существуют быстрые методы перевода через группировку двоичных разрядов:

  • Двоичная → Четверичная: группируем по 2 разряда справа налево
  • Двоичная → Восьмеричная: группируем по 3 разряда справа налево
  • Двоичная → Шестнадцатеричная: группируем по 4 разряда справа налево

Переведём число 101010 из двоичной системы в восьмеричную:

Разделим на 2 группы по 3 разряда: 101 и 010. Переводим каждую группу в восьмеричную систему: 101 = 5, 010 = 2. «Склеиваем» обе цифры в одно число: 52. В итоге получаем, что двоичное число 101010 в восьмеричной системе записывается как 52.

Обратный перевод: из произвольной системы в десятичную

Для перевода числа из системы с основанием N в десятичную используется позиционный принцип – каждая цифра умножается на основание в соответствующей степени:

Число = dₙ × Nⁿ + dₙ₋₁ × Nⁿ⁻¹ + … + d₁ × N¹ + d₀ × N⁰

Для примера давайте переведём ранее полученное число 116 из восьмеричной в десятичную систему: 1 × 8² + 1 × 8¹ + 6 × 8⁰ = 64 + 8 + 6 = 78.

В современных языках программирования уже встроены функции для работы с различными системами счисления. Однако понимание базовых алгоритмов позволяет:

  • Оптимизировать код для специфических задач
  • Работать с нестандартными основаниями
  • Отлаживать низкоуровневые ошибки
  • Создавать собственные высокопроизводительные конвертеры

Владение методами перевода между системами счисления – это не просто школьное упражнение, а практический навык, необходимый каждому программисту для глубокого понимания работы компьютера на фундаментальном уровне.

Далее рассмотрим, как теория воплощается в практике на примере Python.

Программные методы перевода чисел в Python

Python предоставляет набор встроенных функций для наиболее часто используемых систем и удобные инструменты для работы с произвольными основаниями.

Перевод в десятичную систему

Функция int() – универсальная функция для конвертации чисел в десятичную систему. Она принимает строковое представление числа в любой системе счисления с основанием от 2 до 36.

Синтаксис:

int(number_string, base)

Где:

  • number_string – строка с числом в исходной системе
  • base – основание исходной системы (от 2 до 36)
# Из двоичной системы
binary_num = int('101010', 2)

print(binary_num)
>>>42

# Из шестнадцатеричной системы
hex_num = int('ff', 16)

print(hex_num)
>>>255

# Из произвольной системы (7-ричной)
custom_num = int('60', 7)

print(custom_num)
>>>42

Встроенные функции для основных систем

Python предоставляет три специализированные функции для перевода десятичных чисел в наиболее востребованные системы счисления.

bin() – двоичная система

Преобразует целое число в двоичное представление с префиксом «0b»:

x = 42
binary = bin(x)

print(binary)
>>>0b101010

oct() – восьмеричная система

Конвертирует число в восьмеричную форму с префиксом «0o»:

x = 42
octal = oct(x)

print(octal)
>>>0o52

hex() – шестнадцатеричная система

Переводит число в шестнадцатеричное представление с префиксом «0x»:

x = 42
hexadecimal = hex(x)

print(hexadecimal)
>>>0x2a

Удаление префиксов

Как вы могли заметить, вместе с числом в нужной системе счисления выводится ещё и его префикс (0b, 0o, 0x). Зачастую он вовсе не нужен. Давайте рассмотрим способы, как от него избавиться.

Простейший способ избавиться от системных префиксов – использовать срезы строк:

x = 42

print(bin(x)[2:])
print(oct(x)[2:])
print(hex(x)[2:])
>>>101010
>>>52
>>>2a

Но удобнее всё же пользоваться форматированными строковыми литералами (f-строками). В таком случае, можно сразу перевести число в нужную систему счисления и без префикса.

f-строки имеют следующий синтаксис:

f"{число:формат}"

  • число – значение, которое нужно вставить в строку
  • формат – спецификатор формата – строка, задающая способ отображения значения. В нашем случае это будет требуемая система счисления

Обозначения для систем счисления следующие:

  1. b – для двоичной
  2. o – для восьмеричной
  3. x – для шестнадцатеричной

В примере ниже переведём число 42 в различные системы счисления:

num = 42

print(f'{num:b}') # bin
print(f'{num:o}') # oct
print(f'{num:x}') # hex
>>>101010
>>>52
>>>2a

Универсальная функция для произвольных оснований

Встроенные функции Python ограничены тремя системами счисления. Для перевода в другие системы счисления напишем собственную функцию.

Сначала нужно построить алфавит символов. Для систем с основанием больше 10 требуется расширенный алфавит. Модуль string предоставляет готовые константы:

from string import digits, ascii_uppercase

alph = digits + ascii_uppercase

print(alph)
print(alph[0])
print(alph[1])
print(alph[34])
print(alph[-1])
>>>0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ
>>>0
>>>1
>>>Y
>>>Z

Теперь объявим функцию, назовём её convert и зададим два параметра. Функция будет работать с неотрицательными целыми числами:

  • num – десятичное число, которое хотим перевести
  • base – основание системы счисления, в которую переводим (от 2 до 36)
def convert(num, base):

То есть если вызовем convert(42, 2), то num = 42, а base = 2 (число 42 переводим в двоичную систему).

Далее внутри функции составим алфавит символов из модуля string (каждую новую строку будем дописывать к уже созданной функции для наглядности):

def convert(num, base):
    alph = digits + ascii_uppercase

Создадим переменную, в которой будем хранить результат перевода числа:

def convert(num, base):
    alph = digits + ascii_uppercase
    result = ''

После чего напишем основной цикл алгоритма:

def convert(num, base):
    alph = digits + ascii_uppercase
    result = ''
    while num:

Он будет работать, пока num не станет равным нулю. Далее будем находить по одной цифре числа вот такой записью:

def convert(num, base):
    alph = digits + ascii_uppercase
    result = ''
    while num:
        result += alph[num % base]

Разберём по частям, что происходит внутри этой записи:

  1. «num % base» – находим остаток от деления числа на основание системы
    • Например, если num = 42 и base = 2, то 42 % 2 = 0
    • Если num = 21 и base = 2, то 21 % 2 = 1
  2. «alph[num % base]» – используем остаток как индекс в нашем алфавите
    • Если остаток 0, получаем alph[0] = '0'
    • Если остаток 10, получаем alph[10] = 'A'
  3. «result +=» – добавляем полученный символ в конец строки результата

Следующим шагом выполним целочисленное деление числа num на основание системы base:

def convert(num, base):
    alph = digits + ascii_uppercase
    result = ''
    while num:
        result += alph[num % base]
        num //= base

Пример:

  • Если num = 42 и base = 2, то 42 // 2 = 21
  • Если num = 21 и base = 2, то 21 // 2 = 10
  • Если num = 10 и base = 2, то 10 // 2 = 5
  • Если num = 5 и base = 2, то 5 // 2 = 2
  • Если num = 2 и base = 2, то 2 // 2 = 1
    Если num = 1 и base = 2, то 1 // 2 = 0

Таким образом мы «отрезаем» последнюю цифру числа делением нацело и переходим к следующей.

Осталось обработать число 0, вернуть результат в обратном порядке и не забыть импортировать константы из string. Наша функция готова:

from string import digits, ascii_uppercase


def convert(num, base):
    alph = digits + ascii_uppercase
    if num == 0:
        return '0'
    result = ''
    while num:
        result += alph[num % base]
        num //= base
    return result[::-1]

Ну а теперь можно использовать эту функцию для своих вычислений. Давайте проверим её работу на нескольких примерах.

print(convert(42, 2))
print(convert(42, 3))
print(convert(42, 8))
print(convert(42, 27))
>>>101010
>>>1120
>>>52
>>>1F

Итоги

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

Мы детально изучили универсальный алгоритм перевода чисел – метод последовательного деления с записью остатков. Этот фундаментальный алгоритм лежит в основе всех современных методов конвертации. Особое внимание уделили оптимизированным методам для систем с основаниями-степенями двойки, что критически важно для работы с компьютерными данными.

Переход от теории к практике осуществили через программную реализацию на Python. Изучили встроенные функции bin(), oct(), hex(), освоили форматирование через f-строки и создали универсальную функцию для перевода в любую систему счисления. Разобрав её построчно, убедились, что сложные алгоритмы состоят из простых, логичных шагов.

Все эти знания формируют фундамент для решения задания 5 ЕГЭ по информатике, которое проверяет умение работать с различными системами счисления. В следующей статье мы применим полученные знания на практике, разберём типовые задания и научимся эффективно использовать написанные функции.

Разберём эту тему на бесплатном пробном занятии

Преподаватель покажет, как решать такие задачи, и подскажет, с чего начать подготовку. Группы до 8 человек, очно в Калининграде и онлайн.

Записаться на пробное занятие