К содержанию

Задание 5

Формальное исполнение алгоритма

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

5 подтем · 39 задач · базовый · ≈ 4 мин

Подтема 1 из 5

Число и его запись

Число и его запись, перевод в другую систему делением и на Python.

Как устроена тема

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

«На вход алгоритма подаётся натуральное число N. Строится его двоичная запись; если N чётное, к ней справа дописывается 10, если нечётное — 01. Полученная запись — двоичная запись числа R. Найди наименьшее N, для которого R больше 150».

Главное — различать число и его запись: алгоритм работает с цифрами записи, а спрашивают о числах. Сначала разберём, что сказано в условии:

В условииЧто это значит
натуральное число Nвход — целое число 1, 2, 3, …
строится его двоичная записьN пишут нулями и единицами
чётному — справа 10, нечётному — 01к записи справа приписывают две цифры
полученная запись — двоичная запись числа Rновую запись читают как число R
наименьшее N, для которого R больше 150ищем самый маленький вход с таким результатом

Почти всё время будем смотреть на число 13 и его двоичную запись 1101, а для троичной системы — на число 29. Тема состоит из пяти подтем — у каждой своя страница. Идём по ним по порядку:

  1. Число и его запись — ты сейчас здесь.
  2. Дописывание цифр — что происходит с числом, когда к записи приписывают цифры.
  3. Срезы, замены и сумма цифр — другие действия с записью.
  4. Решение перебором — программа для задачи темы — ответ 38.
  5. Решение от результата — та же задача без перебора N.

Каждое действие разобрано и вручную, и в программе на Python. На экзамене подойдёт любой способ, а второй пригодится для проверки.

Число и запись

Число и его запись — разные вещи. Рассмотрим 13₁₀ = 1101₂. Здесь записано одно и то же число, но двумя способами: 13 — его десятичная запись, 1101 — его двоичная запись. Нижний индекс показывает систему счисления. Запись 1101₂ нужно читать как «число, записанное цифрами 1101 в двоичной системе».

При переводе между системами значение числа не меняется. Меняется способ его записи.

Но если к двоичной записи 1101 дописать справа 0, получится 11010₂ = 26₁₀. Это уже другое число.

Поэтому в задании полезно мысленно разделять три объекта:

ОбозначениеЧто означаетПример
NИсходное число13
sЗапись, над которой выполняют действия1101
RЧисло, соответствующее итоговой записиНапример, 26

Алгоритм может выглядеть так:

N = 13 → s = 1101 → s = 11010 → R = 26.

Значение цифры

В позиционной системе значение цифры зависит от её места. Начнём с привычной десятичной записи:

347 = 3 · 100 + 4 · 10 + 7 · 1 = 3 · 10² + 4 · 10¹ + 7 · 10⁰.

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

В двоичной системе принцип такой же, но соседние разряды отличаются по весу в два раза: 1, 2, 4, 8, 16, 32, … В троичной — в три раза: 1, 3, 9, 27, 81, …

Число, определяющее это отношение, называют основанием системы счисления. Дальше обозначим его q, чтобы не путать с исходным числом N.

В системе с основанием q значение каждой цифры меньше q. В двоичной системе цифры только 0 и 1, в троичной — 0, 1, 2, в восьмеричной — от 0 до 7. Поэтому 102 не может быть двоичной записью: цифра 2 в ней недопустима.

Разберём число 1101₂. Под каждой цифрой — вес её разряда, ниже — вклад цифры в число:

Запись 1101₂: веса разрядов справа налево 1, 2, 4, 8. Ноль ничего не добавляет, поэтому 1101₂ = 8 + 4 + 0 + 1 = 13.

Для троичной записи: 1202₃ = 1 · 3³ + 2 · 3² + 0 · 3 + 2 = 27 + 18 + 2 = 47. Для восьмеричной: 157₈ = 1 · 64 + 5 · 8 + 7 = 111.

Отсчёт степеней начинается справа с нуля, потому что крайняя правая цифра показывает количество единиц: q⁰ = 1.

Перевод делением

Перевод в другую систему через деление работает потому, что остаток раскрывает последнюю цифру. Возьмём десятичное число 347: 347 = 34 · 10 + 7. При делении на 10 целая часть частного равна 34, остаток равен 7. То есть остаток даёт последнюю десятичную цифру, а целая часть частного — число без неё.

Так же в любой системе: остаток от деления на основание — последняя цифра записи, целая часть частного — число без неё.

Переведём 29 в троичную систему. Листай схему по шагам: каждое деление даёт одну цифру, и запись растёт справа налево.

  1. Переводим 29 в систему с основанием 3. Цифры записи появятся справа налево.
  2. 29 = 3 · 9 + 2. Остаток 2 — цифра разряда 3⁰, дальше работаем с частным 9.
  3. 9 = 3 · 3 + 0. Остаток 0 — цифра разряда 3¹, дальше работаем с частным 3.
  4. 3 = 3 · 1 + 0. Остаток 0 — цифра разряда 3², дальше работаем с частным 1.
  5. 1 = 3 · 0 + 1. Остаток 1 — цифра разряда 3³, частное 0 — перевод закончен.
  6. Готово: 29 = 1002₃. Первый найденный остаток стоит справа, последний — слева.

Остатки получены в порядке 2, 0, 0, 1. Но сначала мы нашли последнюю цифру, затем предпоследнюю и так далее. Поэтому для обычной записи нужно прочитать остатки в обратном порядке: 29₁₀ = 1002₃. Проверим: 1002₃ = 27 + 2 = 29.

Длина записи

По длине записи видно, в каких пределах лежит число. Выпишем двоичные записи чисел от 1 до 15 и сгруппируем их по длине. Четырёхзначные записи идут от 1000 до 1111, то есть от 8 до 15. Самая маленькая из них — единица и нули, 1000 = 2³. Следующее число, 16 = 10000, уже пятизначное: 2⁴.

Числа от 1 до 15 по длине двоичной записи, L — количество цифр. Каждая группа начинается со степени двойки (1, 2, 4, 8) и кончается перед следующей степенью.
Тонкости:длина записи для любого основания

Если положительное число имеет L цифр в системе с основанием q, то самая маленькая запись такой длины — 100…0, её значение qᴸ⁻¹, а самое маленькое число следующей длины равно qᴸ. Поэтому qᴸ⁻¹ ≤ N < qᴸ.

Например, трёхзначные троичные записи соответствуют числам 3² ≤ N < 3³, то есть 9 ≤ N ≤ 26.

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

Нули в начале записи называют ведущими нулями: 00101₂ = 101₂ = 5. Значение одинаковое, но длина текста разная. Если следующий шаг зависит от длины или положения символов, это различие может оказаться существенным.

Число и строка в Python

В Python удобно хранить число и его запись в разных переменных. Число n = 13 — целое, а запись s = '1101' — , то есть последовательность символов. Кавычки показывают, что перед нами текст. Сравни:

n = 13s = '1101'print(13 + 1)print('13' + '1')print(s + '0')
14 131 11010

Для чисел + означает сложение, для строк — соединение. Соединение строк также называют конкатенацией. Для решения задания достаточно понимать его как «поставить одну запись вслед за другой».

Команда s = s + '0' означает: взять текущее содержимое s, дописать к нему символ 0 и сохранить получившуюся строку обратно в s. Знак = в программе означает присваивание: сначала вычисляется правая часть, затем результат сохраняется в переменной слева. Проверка равенства — двойной знак .

Готовые функции

Готовые функции Python переводят число в запись — строку. В Python возвращает строку '0b1101'. Первые два символа 0b — служебное обозначение двоичной записи. Они не являются её цифрами. Чтобы получить только цифры, берут bin(13)[2:] — строку начиная с символа с номером 2 и до конца. Номера символов и такие подробно разберём в подтеме 3.

Для восьмеричной системы есть oct, для шестнадцатеричной — hex. Обратное преобразование делает int(s, q): читает строку s как запись в системе с основанием q.

print(bin(13)[2:], oct(13)[2:], hex(31)[2:])print(int('1101', 2), int('15', 8), int('1f', 16))print(int('1101'))
1101 15 1f 13 13 31 1101

Важная тонкость: int('1101') даёт одну тысячу сто один, потому что без второго аргумента используется десятичная система. А int('1101', 2) даёт 13.

Для арифметики с цифрами нужны ещё три операции: остаток от деления n % q, целая часть частного n // q и длина строки len(s). Обычное / даёт дробь и здесь не нужно.

Само целое число в переменной не нужно считать «хранящимся в десятичной записи». Число и его текстовое представление — разные объекты. При обычном выводе целого числа Python показывает его десятичную запись.

Своя функция перевода

Для троичной и других систем функцию перевода пишут сами. Готовой функции для троичной записи в Python нет. Но мы уже знаем, как переводить руками: делить на основание и ставить остатки справа налево. to_base повторяет ровно эти действия. Её вызов to_base(29, 3) должен давать строку '1002'. Для оснований от 2 до 10 подойдёт такой код:

def to_base(n, q):    if n == 0:        return '0'     s = ''    x = n     while x > 0:        digit = x % q        s = str(digit) + s        x = x // q     return s  s = to_base(29, 3)print(s)print(int(s, 3))
1002 29

Нажми «Запуск» в шапке блока и пройди программу по шагам: справа видно, как меняются x, digit и s, под кодом — что сделала каждая строка.

Разберём функцию по порядку. Она принимает два значения: n — переводимое неотрицательное целое число, q — основание системы.

Если число равно нулю, результат сразу готов: return возвращает строку '0' и завершает выполнение функции. Ноль обрабатывается отдельно, потому что цикл ниже для него не выполнится ни разу.

s = '' создаёт пустую строку — в неё будем собирать цифры. x = n создаёт рабочую переменную: её будем уменьшать, сохраняя исходное n. Цикл повторяет три действия, пока x больше нуля:

  • digit = x % q находит последнюю цифру;
  • s = str(digit) + s ставит найденную цифру слева от уже собранного результата. Почему слева? Потому что цифры извлекаются с конца: каждая следующая найденная цифра находится левее предыдущих;
  • x = x // q удаляет последнюю цифру из числа, с которым мы работаем.

Это ровно шаги схемы перевода 29 выше: остатки 2, 0, 0, 1 становятся строками '2', '02', '002', '1002'. После этого x станет нулём, цикл завершится.

Тонкости:основания больше 10

Эта версия рассчитана на основания не больше 10. При большем основании для цифр со значениями 10 и выше нужны дополнительные символы, например A, B, C. Универсальное расширение строится так: заводят строку digits = '0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ' и вместо str(digit) используют digits[digit]. Но для двоичных, троичных и восьмеричных задач достаточно первоначальной функции.

Итого

  • Число и записьперевод меняет запись, а не число; дописанная цифра меняет число
  • Разрядего вес — степень основания, отсчёт справа с нуля
  • Перевод делениемостатки — цифры справа налево
  • Длина записизадаёт диапазон чисел: четыре двоичные цифры — от 8 до 15
  • Pythonbin(n)[2:], int(s, q), своя to_base(n, q)

Проверьте себя

Ответь сначала сам, потом открой ответ.

Вопрос 1
Может ли 1203 быть троичной записью? А четверичной? Если может, какое число она обозначает?
ОтветСкрыть ответ
Ответ
Троичной — нет: цифра 3 недопустима. Четверичной — да: 1203₄ = 64 + 2 · 16 + 0 + 3 = 99.
Вопрос 2
Переведи 23 в двоичную систему делением.
ОтветСкрыть ответ
Ответ
23 → остатки 1, 1, 1, 0, 1, справа налево: 10111. Проверка: 16 + 4 + 2 + 1 = 23.
Вопрос 3
Чем отличаются int('101') и int('101', 2)?
ОтветСкрыть ответ
Ответ
Первое читает строку как десятичную запись — 101, второе как двоичную — 5.
Вопрос 4
Сколько чисел имеют четырёхзначную двоичную запись?
ОтветСкрыть ответ
Ответ
8: от 1000 = 8 до 1111 = 15.
Вопрос 5
Почему в функции to_base цифру ставят слева: s = str(digit) + s?
ОтветСкрыть ответ
Ответ
Деление находит цифры с конца: первой — последнюю. Каждая следующая найденная цифра стоит левее уже найденных.

Практика

Для проверки ответов нужен JavaScript. Условия, подсказки и решения доступны ниже.

22 в двоичной и троичной

Переведи 22 в двоичную и троичную системы.

Введите две записи через пробел: двоичную, затем троичную.

Какие числа записаны

Какие числа записаны: 10011₂, 2101₃, 147₈?

Введите три числа через пробел в том порядке, в каком их спрашивают.

Шесть двоичных цифр

Какое наименьшее и какое наибольшее число имеют ровно шесть двоичных цифр? Сколько всего таких чисел?

Введите три числа через пробел в том порядке, в каком их спрашивают.

Длина двоичной записи 1000

Сколько цифр в двоичной записи числа 1000? Ответь без перевода, по границам длины.

Введите число.

Одна запись — три числа

Что выведет программа?

print(int('101', 2), int('101'), int('101', 3))

Введите три числа через пробел в том порядке, в каком их спрашивают.

Пятизначные троичные на отрезке

Сколько натуральных чисел из отрезка [50; 300] имеют в троичной записи ровно пять цифр?

Введите число.

Пять троичных цифр, первая 2

Сколько натуральных чисел, не превышающих 500, имеют троичную запись из пяти цифр, которая начинается с цифры 2?

Введите число.