Модуль 3 · Урок 3.1
Цикл while и состояние программы
Повторение по условию, счётчик и накопитель, почему цикл даёт верный ответ, цифры числа, break и continue.
В модуле «Условия» сумма и наибольшее четырёх чисел потребовали четырёх имён и трёх if. Для тысячи чисел так не напишешь. Цикл повторяет одни и те же строки, пока выполняется условие, — и одна короткая программа обрабатывает сколько угодно данных.
Начнём с простого счёта, научимся накапливать сумму, снимать цифры числа и останавливать цикл досрочно, а в конце решим сквозную задачу для любого количества чисел.
Цикл while
while повторяет блок, пока условие истинно. Перед каждым повторением он проверяет условие. Если оно истинно, выполняется тело цикла — блок с отступом, — и проверка начинается заново. Как только условие ложно, выполнение переходит к строке после цикла. Нажми «Запуск» и посмотри, как выполнение возвращается к строке while:
i = 1while i <= 4: print(i) i += 1Одно выполнение тела называют итерацией. После четвёртой итерации i равно 5, проверка 5 <= 4 ложна, и цикл заканчивается. Если условие ложно с самого начала — например, при i = 10, — тело не выполнится ни разу.
Если забыть i += 1, условие будет истинным всегда — получится бесконечный цикл. Останови его красной кнопкой Stop в панели Run PyCharm или сочетанием Ctrl
Счётчик и накопитель
Счётчик считает события, накопитель собирает результат. Найдём сумму чисел от 1 до 4. Нажми «Запуск» и пройди цикл по шагам:
i = 1total = 0while i <= 4: total += i i += 1print(total)i — следующее число, которое нужно прибавить. total собирает сумму уже обработанных чисел; такая переменная называется накопителем. Переменную, которая считает события, называют счётчиком. Вот значения при каждой проверке условия:
total лежит сумма чисел до i - 1: 0, 1, 1 + 2, 1 + 2 + 3, 1 + 2 + 3 + 4. Четыре проверки дают True и запускают тело, пятая — False, и цикл заканчивается.Сумма начинается с 0: прибавление нуля не меняет результат. Произведение начинают с 1: если начать с нуля, оно навсегда останется нулём.
Как цикл заканчивается
Цикл должен на каждой итерации приближаться к выходу. В сумме чисел i растёт на 1 и неизбежно превысит 4 — значит, цикл закончится. Прежде чем запускать свой цикл, ответь на два вопроса: что хранит каждая переменная перед проверкой — это видно по ленте проверок выше, — и почему условие когда-нибудь станет ложным.
Тонкости:инвариант цикла
Утверждение, которое верно перед каждой проверкой условия, называют инвариантом цикла. Для суммы это «total равен сумме чисел от 1 до i - 1». Перед первой проверкой оно верно: i = 1, сумма пустого набора — 0. Тело прибавляет i и увеличивает i, поэтому утверждение сохраняется. Когда цикл останавливается при i = 5, сложены ровно числа от 1 до 4. Инвариант — не команда Python, а способ доказать, что цикл считает верно.
Цифры числа
Цифры числа снимают по одной справа: % 10 берёт последнюю, // 10 её отбрасывает.
number = -5072n = abs(number)digit_sum = 0while n > 0: digit = n % 10 digit_sum += digit n //= 10print(digit_sum)Это тот же накопитель, только складываются цифры. Проследи n и сумму по шагам:
- n = 5072: последняя цифра n % 10 = 2, n // 10 = 507.
- n = 507: последняя цифра n % 10 = 7, n // 10 = 50.
- n = 50: последняя цифра n % 10 = 0, n // 10 = 5.
- n = 5: последняя цифра n % 10 = 5, n // 10 = 0.
- n = 0 — цикл закончен. Сумма цифр 5072 равна 14.
Каждая итерация снимает последнюю цифру, и следующая видит соседнюю слева. number хранит исходное число, а n — рабочая копия, которую цикл уменьшает. Знак — не цифра, поэтому сначала берут модуль: abs(-5072) — 5072.
Для числа 0 цикл не выполнится ни разу. Сумма цифр 0 при этом верна, а вот количество цифр получится 0, хотя в записи одна цифра. Ноль при подсчёте цифр обрабатывают отдельно.
break и continue
break завершает цикл досрочно, continue пропускает остаток итерации. break сразу завершает цикл, в котором стоит. Это удобно, когда признак окончания становится известен внутри тела. Числа вводятся по одному, 0 — признак конца ввода:
total = 0while True: n = int(input()) if n == 0: break total += nprint(total)while True сам по себе бесконечен: условие всегда истинно, а выход задаёт break. 0 здесь — только признак окончания, в сумму он не входит.
continue пропускает остаток тела и сразу переходит к следующей проверке условия. Сложим нечётные числа от 1 до 5 — пройди по шагам и посмотри, как чётные i перескакивают total += i:
i = 0total = 0while i < 6: i += 1 if i % 2 == 0: continue total += iprint(total)Увеличение i стоит первым, до continue. Если поставить i += 1 в конец тела, на первом же чётном числе continue перескочит его, и цикл никогда не закончится.
Первая степень
Цикл может искать первое значение, которое достигло границы. Найдём наименьшее целое k >= 0, для которого 2 ** k >= n:
n = 17k = 0power = 1while power < n: power *= 2 k += 1print(k)Перед каждой проверкой power — это 2 в степени k. Цикл прекращается при первом достижении границы: 2⁴ = 16 ещё меньше 17, а 2⁵ = 32 уже нет. Для n = 1 ответ 0 получается без единой итерации.
Сквозная задача
Сквозная задача курса: цикл заменяет повторяющиеся if. В уроке о ветвлении сумма и наибольшее из 5, −2, 10, 7 потребовали четырёх имён и трёх if. С while числа можно вводить по одному до признака окончания 0, и программа не зависит от их количества:
n = int(input())total = 0best = nwhile n != 0: total += n if n > best: best = n n = int(input())print(total, best)Первое число читается до цикла: с него начинается best, как в уроке о ветвлении, и его же проверяет условие n != 0. Каждое следующее число читается в конце тела — чтобы проверка увидела его до того, как оно попадёт в сумму. total — накопитель, а три if прошлого урока стали одним if внутри цикла.
Итог
Теперь программа умеет повторять действия, и её длина больше не зависит от количества данных. Вот что из урока понадобится дальше.
whileПроверяет условие перед каждой итерацией; ложное сразу условие — ни одной итерации.- Накопитель и счётчикСумму и счётчик начинают с 0, произведение — с 1.
- Выход из циклаКаждая итерация должна приближать условие к ложному; иначе — бесконечный цикл (Stop в PyCharm, Ctrl
C в терминале). - Цифры числа
n % 10— последняя цифра,n //= 10отбрасывает её; сначалаabs, ноль — отдельно. breakСразу завершает цикл, в котором стоит.continueПропускает остаток тела; изменение переменной условия ставят до него.- Признак окончанияПервое число читают до цикла, следующее — в конце тела; признак (0) в результат не входит.
Проверьте себя
Ответь сначала сам, потом открой ответ.
Сколько раз выполнится тело цикла while i < 5:, если перед ним i = 10?
ОтветСкрыть ответ
Ни разу: первая же проверка 10 < 5 ложна.
Что напечатает программа?
i = 1product = 1while i <= 4: product *= i i += 1print(product)ОтветСкрыть ответ
24 = 1 · 2 · 3 · 4. Произведение начинается с 1: с нулём ответ был бы 0.
Почему цикл while n != 0: n //= 10 никогда не закончится при n = -15?
ОтветСкрыть ответ
-15 // 10 даёт −2, затем −1, а -1 // 10 снова −1: ноль не достигается. Поэтому сначала берут модуль.
Чем опасен такой цикл?
i = 0while i < 5: if i == 2: continue i += 1ОтветСкрыть ответ
При i == 2 continue перескакивает i += 1: i навсегда остаётся 2, и цикл бесконечен.
Программа из урока складывает числа до признака 0 с break. Что она напечатает, если ввести 3, 8, 0, 5?
ОтветСкрыть ответ
11: после 0 цикл закончен, и 5 программа уже не читает.
Практика
Для проверки ответов нужен JavaScript. Условия, подсказки и решения доступны ниже.
Наименьшее k, для которого 2 ** k >= n
Программа ищет наименьшее k, для которого 2 ** k >= n. Запусти её дважды — введи 1, затем 64 — и запиши оба ответа.
n = int(input())k = 0power = 1while power < n: power *= 2 k += 1print(k)Запишите два числа через пробел: для n = 1, затем для n = 64.
Подсказка
При n = 1 условие power < n ложно сразу: цикл не выполнится ни разу.
Разбор
Для 1 цикл не выполняется: 2⁰ = 1. Для 64 цикл удваивает power шесть раз: 2⁶ = 64.
Ответ: 0 6
Что напечатает программа?
i = 1total = 0while i <= 5: total += i * i i += 1print(total)Введите число.
Подсказка
Складываются квадраты чисел от 1 до 5.
Разбор
1 + 4 + 9 + 16 + 25 = 55.
Ответ: 55
Что напечатает программа?
i = 10count = 0while i > 0: i -= 3 count += 1print(count, i)Запишите напечатанные числа через пробел в порядке вывода.
Подсказка
Выпиши i перед каждой проверкой: 10, 7, 4, 1, … — цикл идёт, пока i больше нуля.
Разбор
Перед проверками i равно 10, 7, 4, 1 — четыре итерации; затем −2, и условие ложно.
Ответ: 4 -2
Напиши программу: произведение чисел от 1 до 5
Напиши программу, которая циклом while находит произведение чисел от 1 до 5. Запусти её, затем поменяй начальное значение произведения с 1 на 0 и запусти снова. Запиши оба результата.
Запишите два числа через пробел: с началом 1, затем с началом 0.
Подсказка
Произведение начинают с 1. Ноль, умноженный на что угодно, остаётся нулём.
Разбор
Например:
i = 1product = 1while i <= 5: product *= i i += 1print(product)1 · 2 · 3 · 4 · 5 = 120; с началом 0 произведение всё время 0.
Ответ: 120 0
Напиши программу: сумма и количество цифр
Напиши программу, которая циклом while n > 0 находит сумму и количество цифр числа. Запусти её для 90817, затем для 0.
Запишите три числа через пробел: сумма цифр 90817, количество его цифр, затем количество цифр, которое тот же цикл насчитает для 0.
Подсказка
% 10 — последняя цифра, // 10 — число без неё. Для 0 условие n > 0 ложно сразу.
Разбор
Например:
n = int(input())digit_sum = 0count = 0while n > 0: digit_sum += n % 10 count += 1 n //= 10print(digit_sum, count)9 + 0 + 8 + 1 + 7 = 25, цифр 5. Для 0 цикл не выполняется и насчитывает 0 цифр, хотя в записи одна.
Ответ: 25 5 0
Напиши программу: количество и сумма до нуля
Напиши программу: числа вводятся по одному, ввод заканчивается нулём. Программа печатает количество и сумму введённых чисел без нуля. Запусти её и введи 4, −2, 9, 0.
Запишите два числа через пробел: количество, затем сумму.
Подсказка
Проверь число на ноль и выйди через break; счётчик и сумму меняй после этой проверки.
Разбор
Например:
count = 0total = 0while True: n = int(input()) if n == 0: break count += 1 total += nprint(count, total)Три числа: 4 − 2 + 9 = 11.
Ответ: 3 11
Напиши программу: сколько шагов до 1
Пока число не равно 1, чётное делят пополам, а нечётное заменяют на 3n + 1. Напиши программу, которая считает шаги до 1, и запусти её для 6 и для 27.
Запишите два числа через пробел: шаги для 6, затем для 27.
Подсказка
Цикл while n != 1; на каждой итерации — одна замена и счётчик + 1. Чётность — n % 2 == 0.
Разбор
Например:
n = int(input())steps = 0while n != 1: if n % 2 == 0: n //= 2 else: n = 3 * n + 1 steps += 1print(steps)6 → 3 → 10 → 5 → 16 → 8 → 4 → 2 → 1: 8 шагов. Для 27 программа насчитает 111.
Ответ: 8 111
Напиши программу: цифры числа в обратном порядке
Напиши программу, которая переворачивает цифры числа: из 123 получает 321. Запусти её для 1230 и запиши, что она напечатала.
Введите число.
Подсказка
На каждой итерации: digit = n % 10, result = result * 10 + digit, n //= 10.
Разбор
Например:
n = int(input())result = 0while n > 0: result = result * 10 + n % 10 n //= 10print(result)Для 1230 первая снятая цифра — 0, и в начале числа она исчезает: получается 321.
Ответ: 321