Подтема 2 из 5
Дописывание цифр
Что происходит с числом, когда к его записи дописывают цифры справа или слева.
Дописывание справа
Что получится, если к двоичной записи 11 = 1011 дописать справа 01? А если первые две цифры заменить или посчитать сумму цифр? Задание 5 состоит из таких действий.
Каждое действие с записью — это строка программы и понятное изменение числа: дописанная справа цифра сдвигает старые цифры. Здесь — дописывание; срезы, замены и сумма цифр — в подтеме 3. Функция to_base из подтемы 1 нам ещё понадобится.
Сдвиг разрядов
Дописанная справа цифра сдвигает все старые цифры на разряд влево. В десятичной системе 37 → 374. Что произошло с числом? 374 = 37 · 10 + 4. Все исходные цифры сдвинулись на один разряд влево. Их вклад увеличился в десять раз. В освободившийся разряд единиц поставили 4.
В двоичной системе 1011₂ → 10110₂. Поскольку 1011₂ = 11, получаем R = 11 · 2 + 0 = 22. Если дописать единицу, 1011₂ → 10111₂, то R = 11 · 2 + 1 = 23.
Дописали 0 — число удвоилось, дописали 1 — удвоилось и выросло на 1.
Тонкости:общее правило
Общее правило: R = qN + d, где d — дописанная цифра. У неё обязательно должно выполняться 0 ≤ d < q.
В двоичной системе возможны только два варианта: дописали 0 — R = 2N, дописали 1 — R = 2N + 1. Это не отдельные формулы для заучивания: они следуют из весов разрядов.
Несколько цифр
Если справа дописывают несколько цифр, важны и их значение, и их количество.
Например, к 1011₂ = 11 дописываем 01: 1011₂ → 101101₂. Дописали две цифры: старое число умножилось на 4, и к нему прибавилось значение блока — 44 + 1 = 45.
Особенно внимательно обращайся с нулями в начале дописываемого блока. У блоков 1, 01, 001 одинаковое числовое значение — 1. Но разная длина:
- 1
- R = 2N + 1один разряд: N · 2¹
- 01
- R = 4N + 1два разряда: N · 2²
- 001
- R = 8N + 1три разряда: N · 2³
Например, для N = 11: 11 · 8 + 1 = 89. И действительно, 1011₂ → 1011001₂ = 89.
Нули в начале отдельного блока нельзя выкидывать, если условие требует дописать именно этот блок.
Тонкости:общее правило
Если к записи N в системе с основанием q справа дописывают блок из k цифр со значением A, то R = N · qᵏ + A: каждый сдвиг на один разряд умножает число на q, сдвиг на k разрядов — на qᵏ.
Дописывание слева
Если дописать цифры слева, их вес зависит от длины прежней записи. Пусть N = 11 = 1011₂. Дописали слева 10: 1011 → 101011. Исходные цифры остались на своих местах. Новый блок оказался левее четырёх исходных разрядов. Поэтому R = 10₂ · 2⁴ + 11 = 2 · 16 + 11 = 43.
Тонкости:общее правило
Общее правило: R = A · qᴸ + N, где A — значение дописанного слева блока, L — длина записи, перед которой этот блок ставят. Сравни:
| Действие | Формула |
|---|---|
| Справа дописать k цифр со значением A | N · qᵏ + A |
| Слева дописать блок со значением A | A · qᴸ + N |
Например, если слева дописывается одна единица: R = qᴸ + N. Здесь степень зависит от длины исходной записи. При переходе к следующей длине она меняется.
Если запись содержит сохранённые ведущие нули, в этой формуле нужна фактическая длина записи на данном шаге, а не длина её сокращённой формы.
Соединение строк
В программе дописывание — это соединение строк. Дописать справа 01 — s = s + '01', слева 10 — s = '10' + s. Скопировать в конец последние две цифры — s = s + s[-2:]: s[-2:] берёт два последних символа. Так любая команда условия становится одной строкой программы.
Блок по условию
Чаще всего блок выбирают по условию на N. Например: если N чётное, слева дописать 1, а справа 0; если нечётное — слева 11, а справа 1.
Проверим руками на двух входах. 6 = 110₂, оно чётное: 1 + 110 + 0 = 11100. Справа одна цифра, поэтому старое число удвоилось: 12. Слева единица встала над четырьмя разрядами: 2⁴ = 16. R = 16 + 12 = 28. Число 7 = 111₂ нечётное: 11 + 111 + 1 = 111111, R = 63.
В программе выбор ветви — с else, а чётность — остаток n % 2. Запусти её по шагам и посмотри, какую ветвь проходит каждый вызов:
def transform(n): s = bin(n)[2:] if n % 2 == 0: s = '1' + s + '0' else: s = '11' + s + '1' return int(s, 2) print(transform(6))print(transform(7))Для чётного 6 выполняется строка 4 и пропускается строка 6, для нечётного 7 — наоборот. Посмотрим на результаты подряд:
for n in range(4, 9): print(n, transform(n))Обрати внимание: при N = 8 результат меньше, чем при N = 7. Результат не обязан расти вместе с N, если ветви дописывают разные блоки. Как с этим жить при поиске ответа, разберём в подтеме 4.
Дописать результат
Дописать результат вычисления — не всегда значит применить str. Предположим, алгоритм требует:
- найти остаток от деления N на 3;
- умножить его на 7;
- перевести произведение в троичную систему;
- дописать эту запись справа.
Если остаток равен 2, то 2 · 7 = 14. Но дописывать нужно не 14, а троичную запись: 14₁₀ = 112₃.
n = 14s = to_base(n, 3)extra = n % 3 * 7print(s + to_base(extra, 3))print(s + str(extra))Первая строка правильная: дописана троичная запись 112. Вторая неправильная: str(14) даёт десятичную строку '14'. Более того, цифра 4 вообще недопустима в троичной записи.
Применять str можно, когда дописывается одна допустимая цифра нужной системы, например str(n % 2). Например, остаток от деления на 2 — это 0 или 1.
Каждый раз задавай себе вопрос: я дописываю одну цифру или запись некоторого числа в указанной системе?
Итого
- Дописать справастарые цифры сдвигаются: одна двоичная цифра — число удвоилось, две — умножилось на 4
- Блок 01 и 001длина блока важна вместе с нулями в его начале
- Дописать слевастарые цифры не двигаются, блок встаёт над ними
- Блок по условиюif и else по условию на N; результат может не расти вместе с N
- Записанное числодописывают его запись в нужной системе, а не str
Проверьте себя
Ответь сначала сам, потом открой ответ.
1011 дописали справа 0, затем 1. Чему равно R?ОтветСкрыть ответ
1011 → 10110 = 22 → 101101 = 45 — число удвоилось, потом удвоилось и выросло на 1.s + str(2 * 4) не годится, если к двоичной записи нужно дописать двоичную запись произведения?ОтветСкрыть ответ
str(8) даёт десятичное '8', а нужна двоичная запись 1000: s + bin(2 * 4)[2:].1101 дописали слева 1. Чему равно R?ОтветСкрыть ответ
11101 — новая единица встала над четырьмя разрядами, её вес 16, и 16 + 13 = 29.1 и 001 имеют одно значение. Дают ли они одинаковое R?ОтветСкрыть ответ
001 сдвигает старые цифры на три разряда, а 1 — на один. Для N = 11 получится 89 и 23.Практика
Для проверки ответов нужен JavaScript. Условия, подсказки и решения доступны ниже.
Дописать справа 001
К двоичной записи числа 11 дописали справа 001. Какое число получилось?
Введите число.
Подсказка
Блок из трёх цифр сдвигает число на три разряда: умножение на 8.
Решение
Блок 001 занимает три разряда: старое число умножается на 8 и к нему прибавляется значение блока 1. R = 11 · 8 + 1 = 89.
Решение программой
print(int(bin(11)[2:] + '001', 2))Ответ: 89
Троичный блок 12
К троичной записи числа 7 дописали справа 12. Какое число получилось?
Введите число.
Подсказка
Два троичных разряда — умножение на 9, блок 12 равен 5.
Решение
7 · 9 + 5, блок 12 занимает два троичных разряда и равен 5.
Решение программой
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 print(int(to_base(7, 3) + '12', 3))Ответ: 68
Дописать слева 10
К двоичной записи числа 13 дописали слева 10. Какое число получилось?
Введите число.
Подсказка
Дописанная слева единица стоит на разряде, равном длине записи 13.
Решение
У записи 13 = 1101 четыре разряда, поэтому блок 10 слева встаёт над ними с весом 2⁴: R = 2 · 16 + 13 = 45.
Решение программой
print(int('10' + bin(13)[2:], 2))Ответ: 45
Дописать запись другого числа
К двоичной записи числа 6 дописали справа двоичную запись числа 5. Найди результат формулой и проверь программой.
Введите число.
Подсказка
Запись 5 — 101, три разряда: R = 6 · 8 + 5.
Решение
Запись 101 — три разряда, R = 6 · 8 + 5; 110101₂ = 53.
Решение программой
print(int(bin(6)[2:] + bin(5)[2:], 2))Ответ: 53
Блоки по чётности, R > 200
На вход алгоритма подаётся натуральное число N. Строится двоичная запись N. Если N чётное, слева к ней дописывается 1, а справа — 0; если нечётное, слева дописывается 11, а справа — 1. Полученная запись — двоичная запись числа R. Укажи наименьшее N, для которого R больше 200.
Введите число.
Подсказка
Перебирай N по возрастанию и строй запись по ветви чётности.
Решение
17 = 10001₂, получаем 11100011₂ = 227. При N = 16 получается 96, при N = 15 — 127.
Решение программой
n = 1while True: s = bin(n)[2:] if n % 2 == 0: s = '1' + s + '0' else: s = '11' + s + '1' if int(s, 2) > 200: print(n) break n += 1Ответ: 17
Троичный алгоритм, R > 500
На вход алгоритма подаётся натуральное число N. Строится троичная запись N. Если N делится на 3, справа к ней дописываются две последние троичные цифры этой записи; иначе остаток от деления N на 3 умножается на 8, переводится в троичную систему и дописывается справа. Полученная запись — троичная запись числа R. Укажи наименьшее N, для которого R больше 500.
Введите число.
Подсказка
Дописывается троичная запись произведения, а не str.
Решение
20 = 202₃, остаток 2, 2 · 8 = 16 = 121₃, R = 202121₃ = 556. Все N от 1 до 19 дают R не больше 500.
Решение программой
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 n = 1while True: s = to_base(n, 3) if n % 3 == 0: s = s + s[-2:] else: s = s + to_base(n % 3 * 8, 3) if int(s, 3) > 500: print(n) break n += 1Ответ: 20