Текст
                    1


Валерий Рубанцев Программирование для всех Python. Наглядное программирование на Питоне 2
Бесплатное издание Все права защищены. Никакая часть этой книги не может быть воспроизведена в любой форме без письменного разрешения правообладателей. Автор книги не несёт ответственности за возможный вред от использования информации, составляющей содержание книги и приложений. Copyright 2022 Валерий Рубанцев Лилия Рубанцева 3
От автора В России Питон используется в учебных целях, и это вполне объяснимо. На уровне процедурного программирования Питон не имеет себе равных среди современных языков. Программы, написанные на Питоне, как правило, короче и яснее, чем, например, на Си-шарпе. В Питоне значительно меньше типов данных, что позволяет избежать многих проблем с их выбором и приведением. Тип int в Питоне даёт возможность работать с целыми числами произвольной длины, а тип Decimal – с вещественными числами любой точности. С их помощью можно разрабатывать простые, но эффективные программы для решения математических, физических, химических и других задач, связанных с обработкой числовой информации. К несомненным достоинствам Питона следует отнести также: • он бесплатен • популярен во всём мире • прост в изучении, но используется профессиональными программистами • универсален • один и тот же исходный код можно запустить на компьютерах с любой из распространённых операционных систем: Windows, Mac OS X, Linux Из этого вполне можно сделать вывод, что Питон – лучший выбор в качестве первого языка программирования. Вот традиционно первая программа на языке Питон: print("Hello World") То есть достаточно одной строки, чтобы написать работающую программу. Я недаром выделил слово написать. Для начинающих программистов набрать текст с клавиатуры без ошибок – задача непростая. Не менее сложно для юных программистов и ориентироваться в многострочной текстовой программе. Чтобы облегчить изучение программирования для начинающих, были созданы языки визуального программирования, самым известным из которых является Скретч (Scretch) (Рис. 1). На Рис. 1 хорошо видно, что программа состоит из разноцветных блоков, которые можно перемещать мышкой. Блоки заранее подготовлены, поэтому дополнительная работа по написанию кода для них не нужна, и ошибиться в названиях операторов невозможно. Некоторые блоки требуют ввода данных с клавиатуры, но обычно текста не очень много, и он не 4
может привести к существенным ошибкам в программе. Поэтому основная работа начинающего программиста сводится к разработке алгоритма, а не к набору текста. Рис. 1 Большинство языков визуального программирования – это самостоятельные языки, у которых нет продолжения. Поэтому Скретч рассматривается как подготовка к программированию на настоящем языке. В книге Программирование для детей (Рис. 2) этот переход прямо обозначен. Рис. 2 5
Но в книге после визуального программирования на Скретче сразу следует переход к текстовому программированию на Питоне. Но есть способ лучше! На сайте EduBlocks начинающий программист может начать программировать на языке Питон в визуальной среде и параллельно – в текстовой. Здесь отсутствует подготовительный визуальный язык, который только для этого и нужен, а сразу используется настоящий язык программирования Питон. В этой книге мы будем изучать программирование на Питоне в визуальной среде разработке программ EduBlocks. Вот так выглядит первая программа на Питоне в визуальной среде разработки (Рис. 3). Рис. 3 Вся программа построена из разноцветных блоков, как и в Скретче. Но справа от области визуального редактирования начинающий программист видит и текстовый вариант этой программы (Рис. 4). Рис. 4 Такая «билингва» особенно хороша в начале изучения Питона, когда начинающий программист ещё ничего не знает об языке программирова- 6
ния. Познакомившись с ключевыми словами и функциями языка, он может использовать их и в визуальных программах, и в текстовом виде. В EduBlocks есть замечательный блок, в окошечко которого можно вставить текстовую строку (Рис. 5). Рис. 5 Я, например, просто скопировал её из исходного текста. Так, строка за строкой, начинающий программист может освоить и текстовый вариант программирования на Питоне. Визуальный язык программирования очень хорош на начальном этапе изучения Питона. Но программы из блоков занимают много места на экране, поэтому не следует писать большие программы. Также нужно учитывать, что визуальный язык программирования в принципе не может охватить все возможности Питона. Но в EduBlocks вполне достаточно блоков, чтобы выучить основы программирования на Питоне: - математические операции, целые, вещественные и случайные числа, строки, операции приведения типов - выражения, идентификаторы, ключевые слова, комментарии - константы, литералы, переменные - операторы и инструкции - определения и присваивания, комбинированные операторы - логический тип, операторы и операции отношения, логические выражения, побитовые операции, приоритеты операций - условный оператор if-elif-else - циклы for, while - списки, цикл for-in - функции, формальные и фактические параметры, вызов функций, рекурсия 7
Заучивать ключевые слова, операторы и прочие премудрости языка программирования так же скучно, как и зубрить таблицу умножения, поэтому в книге есть множество занимательных проектов, в которых используются полученные знания. А в конце многих занятий имеются задания для самостоятельного решения. На последнем занятии начинающие программисты познакомятся с классами и черепашьей графикой, которая ещё интереснее программистских задач. Автор 8
Оглавление Python. Наглядное программирование на Пит оне .............. 2 От автора ............................................................... 4 Оглавление ............................................................. 9 Занятие_1. Устанавливаем Пит он на компьютер ................. 14 Занятие_2. Числа в математике и в программах на Пит оне ... 24 Математические операции с целыми числами ............................................. 30 Математические операции с вещественными числами .............................. 36 Дополнительные операции с числами ............................................................ 37 Преобразование и приведение числовых типов ........................................... 39 Обобщение ................................................................................................................. 42 Занятие_3. Практикум по вычислительным задачам ............. 46 Кошки-мышки ............................................................................................................ 46 Шахматная задача ..................................................................................................... 47 Число шахматных партий ..................................................................................... 50 Какая разница? .......................................................................................................... 51 Складывание бумаги ............................................................................................... 52 Три цифры - раз ....................................................................................................... 57 Три цифры - два ....................................................................................................... 59 Гугол ............................................................................................................................ 62 Задача Рачинского .................................................................................................... 64 Вычисление сложных арифметических выражений .................................... 65 Обобщение ................................................................................................................. 66 Занятие_4. Грамматика Пит она ..................................... 68 Выражения .................................................................................................................. 72 Идентификаторы ...................................................................................................... 72 Ключевые (зарезервированные) слова ............................................................. 73 Как правильно выбрать имя .................................................................................. 74 Комментарии ............................................................................................................. 77 Обобщение ................................................................................................................. 79 Занятие_5. Переменные и константы .............................. 81 Переменные .............................................................................................................. 84 9
Константы ................................................................................................................... 85 Именованные константы ........................................................................................ 85 Литералы .................................................................................................................... 87 Обобщение ................................................................................................................. 88 Занятие_6. Визуальное программирование ........................ 89 Занятие_7. Визуальная арифметика .............................. 109 Калькулятор ..............................................................................................................116 Кошки-мышки .......................................................................................................... 124 Шахматная задача ................................................................................................... 124 Число шахматных партий ................................................................................... 125 Какая разница? ........................................................................................................ 128 Складывание бумаги ............................................................................................. 128 Три цифры - раз ..................................................................................................... 130 Три цифры - два ..................................................................................................... 130 Гугол ...........................................................................................................................131 Задача Рачинского ...................................................................................................131 Вычисление сложных арифметических выражений .................................. 132 Занятие_8. Операции и операторы ............................... 133 Выражения ................................................................................................................ 134 Инструкция определения .................................................................................... 137 Инструкция присваивания ................................................................................... 138 Проект Периметр правильного треугольника ............................................. 139 Проект Периметр квадрата ................................................................................. 144 Проект Длина окружности .................................................................................. 145 Проект Прямоугольный треугольник ............................................................. 146 Проект Обмен значениями .................................................................................. 147 Проект Фаренгейт .................................................................................................. 150 Проект Цельсий ..................................................................................................... 152 Обобщение ............................................................................................................... 153 Задания для самостоятельного решения ....................................................... 153 Занятие_9. Математические операции ........................... 156 Проект Арифметические операции ................................................................ 158 Комбинированные операторы присваивания ................................................ 160 Класс Math ............................................................................................................... 162 Случайные числа.................................................................................................... 167 Модуль random (Случайные числа) ...................................................................171 10
Проект Двузначное число ................................................................................... 173 Проект Цифры трёхзначного числа ................................................................ 173 Проект Найти сотни .............................................................................................. 174 Проект Разноциферные числа ........................................................................... 175 Проект Четырёхзначные палиндромы ............................................................ 177 Проект Где точка? ................................................................................................. 178 Проект Белое поле ............................................................................................... 179 Обобщение ................................................................................................................181 Задания для самостоятельного решения ........................................................181 Занятие_10. Логические переменные и операторы ............. 183 Логический тип ...................................................................................................... 183 Операторы и операции отношения (сравнения) .......................................... 185 Условные логические операции....................................................................... 190 Побитовые операции ........................................................................................... 195 Таблица истинности ............................................................................................. 197 Приоритеты операций ......................................................................................... 197 Вычисление логических выражений ............................................................... 199 Проект Истина или Ложь? .................................................................................. 201 Проект Числовая середина ................................................................................ 202 Проект Только одно число ................................................................................ 203 Обобщение .............................................................................................................. 205 Занятие_11. Управляющие структуры ............................ 206 Блок-схемы алгоритмов ..................................................................................... 208 Условный оператор If ......................................................................................... 209 Проект Большее из двух чисел ......................................................................... 216 Вложенные условные операторы ..................................................................... 218 Проект Положительные числа ......................................................................... 221 Проект Одно больше другого ........................................................................... 222 Проект Самое маленькое число....................................................................... 223 Проект Где точка 2? ............................................................................................. 224 Проект Время года ............................................................................................... 225 Обобщение .............................................................................................................. 226 Задания для самостоятельного решения ...................................................... 226 Занятие_12. Циклы................................................. 227 Цикл for ................................................................................................................... 229 Проект Кролики и фазаны ................................................................................. 235 Проект Репетитор ................................................................................................. 239 11
Проект Факториал ................................................................................................. 242 Цикл while ................................................................................................................ 245 Проект Числа Фибоначчи.................................................................................... 249 Проект Collatz ........................................................................................................ 252 Вложенные циклы ................................................................................................ 257 Проект Олимпиадная задача ............................................................................ 257 Бесконечные циклы ............................................................................................. 259 Досрочный выход из цикла ............................................................................... 262 Оператор break ...................................................................................................... 264 Оператор continue ................................................................................................. 267 Какой цикл выбрать? ............................................................................................ 268 Обобщение ............................................................................................................... 271 Задания для самостоятельного решения ...................................................... 272 Занятие_13. Списки ................................................ 274 Создание списков .................................................................................................. 276 Обращение (доступ) к элементам списка ..................................................... 279 Оператор цикла for-in для списков ................................................................ 282 Многомерные списки .......................................................................................... 284 Проект Таблица умножения .............................................................................. 286 Проект Лото............................................................................................................ 289 Обобщение .............................................................................................................. 293 Задания для самостоятельного решения ...................................................... 294 Занятие_14. Функции ............................................... 295 Формальные и фактические параметры ........................................................ 299 Проект Параметр-список ................................................................................... 302 Необязательные и именованные параметры ............................................... 303 Рекурсия ................................................................................................................... 307 Проект Рекурсивное умножение ....................................................................... 310 Проект Рекурсивный модуль...............................................................................311 Проект Рекурсивный факториал ....................................................................... 312 Проект Рекурсивные перевороты ..................................................................... 317 Проект Треугольные числа ................................................................................ 321 Проект Рекурсивные числа Фибоначчи .......................................................... 323 Проект Числовые рекурсии ............................................................................... 326 Проект Великолепная четвёрка ....................................................................... 330 Проект Рекурсивный тортик .............................................................................. 332 Проект Рекурсивный тортик 2 .......................................................................... 335 12
Обобщение .............................................................................................................. 336 Занятие_15. Решаем задачи ....................................... 338 Признаки делимости чисел .............................................................................. 338 Проект Делится - не делится? ......................................................................... 344 Задачи с сайта Проект Эйлер ............................................................................ 351 Проект Задача 1 с сайта Проект Эйлер ......................................................... 352 Проект Четыре числа .......................................................................................... 356 Проект Совершенные числа .............................................................................. 358 Проект Дружественные числа .......................................................................... 360 Проект Назойливый остаток ............................................................................. 363 Проект Шестизначное число ............................................................................. 368 Проект Любопытное свойство чисел ............................................................ 370 Проект Как определил ошибку Чохбилмиш? .............................................. 373 Проект Шестизначный перенос ........................................................................ 375 Проект Наименьшее число ................................................................................ 376 Проект Трёхзначное число ................................................................................ 378 Проект Задача Клайва Синклера ...................................................................... 379 Задания для самостоятельного решения ...................................................... 388 Занятие_16. Черепашья графика .................................. 390 Классы ...................................................................................................................... 399 Цвет в компьютерной графике ......................................................................... 404 Проект Случайные цвета ..................................................................................... 412 Проект Пунктир ...................................................................................................... 414 Полярная система координат ............................................................................ 418 Проект Брейк .......................................................................................................... 420 Проект Полярная Черепашка ............................................................................ 422 Проект Полярная Черепашка 2 ........................................................................ 423 Проект Многоугольники..................................................................................... 426 Проект Черепашьи загогулины ........................................................................ 433 Проект Рекурсивная Черепашка ........................................................................ 436 Проект Звёздчатая Черепашка .......................................................................... 443 Литература .......................................................... 446 13
Занятие_1. Устанавливаем Питон на компьютер Программирование начинается с установки интерпретатора языка на компьютер. Для «тяжёлых» языков программирования типа Си-шарпа это длительная процедура. С Питоном всё гораздо проще и приятнее. Перейдите на официальный сайт языка программирования Питон: https://www.python.org/ и нажмите строчку с последней версией установщика (Рис. 1). Рис. 1 На новой странице щёлкните по строчке с нужным установщиком (Рис. 2). Рис. 2 Выбирайте установщик для той операционной системы, которая стоит на вашем компьютере. 14
Не всегда нужна самая новая версия Питона. Если вы хотите установить более раннюю версию, то найдите в конце страницы секцию Downloads и нажмите строчку All releases (Рис. 3). Рис. 3 На следующей странице выберите нужную версию установщика (Рис. 4). Рис. 4 Установочный файл python-3.10.5-amd64.exe очень небольшой, поэтому быстро окажется на вашем компьютере. Найдите его на диске и дважды щёлкните мышкой. 15
В открывшемся диалоговом окне поставьте галочку Add Python 3.10 to PATH, чтобы интерпретатор запускался Питона без указания пути к нему (Рис. 5). Рис. 5 Щёлкните по строчке Customize installation (Рис. 6). Рис. 6 16
В новом диалоговом окне нажмите кнопку Next (Рис. 7). Рис. 7 По умолчанию все файлы будут установлены в очень далёкой папке. Лучше если это будет корневая папка на рабочем диске С:. Теперь нажмите кнопку Install (Рис. 8). Рис. 8 17
Распаковка и установка всех файлов на компьютер займёт некоторое время. Ход установки показывает зелёная полоска (Рис. 9). Рис. 9 Установка завершена. Нажмите кнопку Close в последнем диалоговом окне (Рис. 10). Рис. 10 18
Откройте список установленных файлов (Рис. 11). Рис. 11 Вместе с интерпретатором Питона и документацией вы получаете простую среду разработки IDLE (Integrated Development and Learning Environment – интегрированная среда для разработки программ и обучения). Перетащите строчку IDLE (Python 3.10 64-bit) на Рабочее окно, чтобы создать ярлык для удобного запуска среды разработки программ (Рис. 12). Рис. 12 Дважды щёлкните по ярлыку, чтобы открыть диалоговое окно IDLE Shell 3.10.5 (Рис. 13). Рис. 13 19
После трёх значков >>> вы увидите текстовый курсор, который приглашает нас к вводу команд для непосредственного выполнения. Обычно первая «программа» на любом языке программирования передаёт привет Миру. Но это слишком пафосно для начинающих программистов. Мы последуем примеру Мартышки из мультика и передадим привет Питону, который тоже почти Удав (Рис. 14). Рис. 14 В мультике про Маугли вы могли видеть настоящего питона Каа (Рис. 15). Рис. 15 20
На самом деле язык программирования Питон не имеет отношения к змеям. Создатель языка Питон – Гвидо ван Россум - назвал его в честь любимого комического шоу Монти Пайтон (Monty Python's Flying Circus – летающий цирк Монти Пайтона) (Рис. 16). Рис. 16 В титрах фильма Монти Пайтон и Священный грааль вы найдёте Эрика Айдла (Eric Idle) (Рис. 17), которого мы можем заподозрить в родстве со средой разработки IDLE. Рис. 17 Однако на логотипе Питона традиционно изображают 2 змеи (Рис. 18). 21
Рис. 18 Мы будем придерживаться змеиной версии названия языка. Уроки русского языка подсказывают нам, что любое приветствие – это строка. В Питоне строки, как и прямая речь на письме, обрамляются двойными или одинарными кавычками. Наберите с клавиатуры строкуприветствие (Рис. 19). Рис. 19 Нажмите клавишу ВВОД, и среда разработки выполнит вашу команду. В данном случае она просто напечатает ту же самую строку, только в одинарных кавычках (Рис. 20). Рис. 20 Обратите внимание, что набранная с клавиатуры строка – ввод - печатается зелёным цветом, а результат выполнения команды (вывод) – синим. Так мы легко отделим команду и результат её выполнения. Как вы видите, строка – это не команда, поэтому среда разработки просто возвращает нам ту же самую строку. Но клавиша ВВОД подаёт команду среде разработки, которая решает, что нужно сделать со строкой пользователя. 22
Все компьютеры любят считать. Пусть Питон найдёт сумму двух двоек (Рис. 21). Рис. 21 Здесь ввод выделен чёрным цветом, то есть числа и строки на экране различаются цветом. Результат сложения верный, поэтому мы смело можем доверить Питону все арифметические вычисления, чем мы и займёмся в следующей главе. Строка 2 + 2 – это арифметическое выражение, а не команда, но клавиша ВВОД заставляет выполнить нашу команду – то есть вычислить арифметическое выражение. Вы должны различать команды языка Питон и команды среды выполнения. Клавиша ВВОД – это команда для среды разработки выполнить введённую строку. Сама строка пользователя может и не быть командой языка Питон. Команда в языке Питон – это вызов функции, о чём вы скоро узнаете. 23
Занятие_2. Числа в математике и в программах на Питоне Числа правят миром. Пифагор Говорят, что числа правят миром. Нет, они только показывают, как правят миром. Иоганн Гёте Детский компьютер Как вы знаете из уроков математики, чисел бесконечно много, но их можно разбить на отдельные (под)множества по тем или иным признакам. Самые первые числа, которые придумали ещё первобытные люди, называются натуральными. Они используются для подсчёта различных предметов, например, яблок или палочек, на которых вы и сами учились считать в первом классе. Папа спрашивает у сына: - Скажи, сколько будет, если к трём грушам прибавить ещё две груши? Сын отвечает: - Не знаю, папа, мы в школе решаем задачи только про яблоки! Множество натуральных чисел обозначается большой латинской буквой N, поэтому само множество можно записать так: N = {1, 2, 3, ...}. Иногда к множеству натуральных чисел относят и нуль (отсутствие предметов 24
вообще): N0 = {0, 1, 2, 3, ...}. Множество натуральных чисел является подмножеством всех чисел и также бесконечно. Если к натуральным числам добавить отрицательные целые числа (и нуль), то получится множество целых чисел. Оно обозначается большой латинской буквой Z = {... -2, -1, 0, 1, 2, ...}. Нетрудно догадаться, что и целых чисел бесконечно много. В арифметике обычно используют именно целые числа, но встречаются алгебраические и геометрические задачи, которые невозможно решить без дробных чисел. Рациональные числа можно представить в виде простой (обыкновенной) дроби: m/n где: • m - целое число; • n - натуральное число, не равное нулю (вы, конечно, помните, что на нуль делить нельзя!). Множество рациональных чисел обозначается буквой Q. Если знаменатель дроби равен 1, то вся дробь равна числителю, то есть целому числу n. Таким образом, все целые числа являются в то же время и рациональными (множество целых чисел - это подмножество рациональных). Но не наоборот! Рациональные числа можно представить также в виде конечной десятичной дроби (1/2 = 0,5) или бесконечной периодической десятичной дроби (1/7 = 0,142857142857...). Иррациональные числа не могут быть представлены в виде простой дроби (а также в виде конечной или бесконечной десятичной периодической дроби). Таким образом, иррациональным числом называют любое число, представимое в виде бесконечной непериодической десятичной дроби. Примером такой дроби служит корень квадратный из двойки. Ир25
рациональность этого числа была известна уже древним математикам, которые доказали несоизмеримость стороны и диагонали квадрата. Иррациональные числа обозначают буквой I. Множество действительных, или вещественных чисел объединяет множества рациональных и иррациональных чисел. Их принято наглядно представлять в виде точек на числовой прямой (Рис. 1). Рис. 1. Числовая прямая Множество действительных чисел обозначают буквой R (от их латинского названия numerus realis). К иррациональным числам относятся знаменитые числа - π (пи, отношение длины окружности к диаметру) и е (основание натуральных логарифмов). Все рассмотренные нами числа - это подмножества комплексных чисел. Их можно представить в виде: a + bi где: • a, b - вещественные числа; • i – мнимая единица. Множество комплексных чисел обычно обозначается буквой С (от латинского слова complex). Наглядно связь между множествами чисел показывает Рис. 2. В программах на языке Питон чаще всего используют такие числовые типы данных: int – для целых чисел произвольной длины float – для вещественных чисел 26
Рис. 2 В записи вещественных чисел обязательно должна быть десятичная точка (а не запятая, как в математике!), если даже дробная часть отсутствует: 5.0 3. -7.123 Ноль целых можно не указывать, а сразу ставить точку: .5 В записи целых чисел десятичной точки быть не должно! Типу float соответствует тип double в других языках программирования. Точность вещественных чисел ограничена 17 знаками. Переменные типа float могут хранить числа в диапазоне: 2.2250738585072014e-308…1.7976931348623157e+308 Таким образом, очень маленькие и очень большие по абсолютной величине числа хранить в вещественных переменных нельзя! Для работы с комплексными числами имеется тип complex. 27
Модуль fractions умеет выполнять арифметические рациональными числами (натуральными дробями). действия с В третьей версии Питона появился модуль decimal, помощью которого легко манипулировать вещественными числами произвольной точности. Кроме собственно чисел, нам понадобятся и два «числовых» модуля. Модуль math нужен для математических вычислений, а модуль random – для генерирования случайных чисел. На следующей странице вы можете снять учебный стресс, выполнив (если желаете – на время) забавный числовой тест. 28
Последовательно найдите числа от 1 до 100! 29
Математические операции с целыми числами Целые числа в программах на Питоне можно складывать и вычитать точно так же, как это делается в арифметике. Простые арифметические вычисления удобно проводить в среде разработки IDLE. Запустите IDLE и вычислите следующие выражения (Рис. 1). Рис. 1 Как видите, знаки операций сложения и вычитания совпадают с математическими. В арифметических выражениях может быть сколько угодно чисел (операндов). Знак операции в программировании называют оператором, а числа, которые участвуют в операции, - операндами. Запись, состоящая из операторов, операндов и круглых скобок, называется выражением. Если выражение состоит только из арифметических операций, то оно называется арифметическим. Между числами и знаками арифметических операций может быть любое число пробелов, но допустимо печатать их и вплотную друг к другу. Последний способ записи выражений сокращает запись, но делает её трудно читаемой. Лучше между знаками операций и операндами ставить ровно 1 пробел. Результат всегда вы всегда получите верный: Питону пробелы не нужны, а вот вам или пользователям вашей программы небезразлично, как вы оформите исходный текст программы, поэтому всегда разделяйте числа и знаки ровно одним пробелом. 30
Перед положительными числами можно ставить знак +, но этого обычно не делают. А вот перед отрицательными числами обязательно должен стоять знак – (Рис. 2). Рис. 2 Знаки операций умножения и деления отличаются от принятых в математике. Для умножения используют звёздочку (астериск), а для деления – косую дробную черту. Не путайте математическую звёздочку астериск с героем комиксов и мультфильмов Астериксом! В результате умножения целых чисел всегда получается целое число. А в результате деления – вещественное, если даже первое число делится нацело на второе (Рис. 3). Рис. 3 31
В записи вещественного числа (десятичной дроби) обязательно присутствует точка, которая отделяет целую часть от дробной. В записи целых чисел точки быть не может. По этому признаку вы легко распознаете целые и вещественные числа (как и Питон). В России и многих других странах в качестве десятичного разделителя используют запятую. Будьте внимательны: в Питоне запятая разделяет разные числа. Запомните: знак / (дробная косая черта, слеш, слэш, slash) обозначает вещественное деление. Для целочисленного деления используют пару таких знаков (Рис. 4). Рис. 4 Результат целочисленного деления имеет тип int. Если в результате целочисленного деления получается вещественное число (то есть первое число не кратно второму), то оно округляется до ближайшего меньшего целого числа (Рис. 5). Рис. 5 В первом случае: 11 : 2 = 5,5 → 5 (для положительных чисел результат - это целая часть вещественного числа). Во втором случае: -11 : 2 = -5,5 → -6 (для отрицательных чисел результат это целая часть вещественного числа минус 1). В Питоне целые числа имеют тип int (сокращение слова integer - целый). Вещественные числа имеют тип float (плавающий десятичный разделитель) Все числа в Питоне – это объекты (экземпляры) какого-либо класса. 32
Арифметические операции с целыми и вещественными числами выполняются по-разному – будьте внимательны! Чтобы узнать тип числа (это просто) или выражения, запишите число или выражение в круглых скобках после ключевого слова type (тип). Питон подскажет вам тип числа или выражения (класс, объектом которого является число или выражение): Ещё один парный знак (2 звёздочки) обозначает операцию возведения в степень. Показатель степени может быть целым и вещественным (Рис. 6). Рис. 6 В первом случае результат – целое число, во втором и третьем – вещественное. И последняя арифметическая операция – деление по модулю. Знак операции тоже может вызвать удивление – это знак %, которым в математике обозначают проценты. В программировании проценты не нужны, поэтому этот знак приспособили под другие цели. Результат выполнения операции деления по модулю - остаток от деления первого числа на второе (Рис. 7). Рис. 7 Если остаток от деления равен нулю, то первое число нацело делится на второе, то есть кратно ему. Мы знаем, что чётными называются числа, которые кратны двум. Например, число 2022 – чётное (Рис. 8). 33
Рис. 8 Если же остаток от деления числа на двойку не равен нулю, то число называется нечётным (Рис. 9). Рис. 9 Операция деления с остатком для положительных чисел вам хорошо известна по школьным урокам. Остаток от деления отрицательных чисел вычисляется более сложно (Рис. 10). Рис. 10 Чтобы найти остаток от деления отрицательного числа a на положительное число b, нужно из числа b вычесть остаток от деления a на b: -a % b = b – a % b (1) Для первого случая мы получаем 3: -9 % 4 = 4 – 9 % 4 = 3 Если a положительное, а b отрицательное, то в формуле (1) нужно изменить знаки на противоположные: a % -b = -b + a % b Для второго случая мы получаем -3: 9 % -4 = -4 + 9 % 4 = -3 Если оба числа отрицательные, то остаток от деления вычисляется, как для положительных чисел, но со знаком минус: -a % -b = -(a % b) В третьем случае получаем -1: 34
-9 % -4 = -(9 % 4) = -1 Остаток от деления вещественных чисел вычисляется по этим же правилам. В математике остаток от деления не может быть отрицательным, поэтому либо будьте внимательны при выполнении таких операций, либо избегайте их. Все арифметические операции выполняются слева направо согласно их приоритетам: • сначала возведение в степень • затем умножение и деление • и в последнюю очередь – сложение и вычитание. Последовательность выполнения арифметических операций можно изменить с помощью скобок - точно так же, как в математике. Но в программах на Питоне скобки в арифметических выражениях должны быть только круглые, но не квадратные и не фигурные, которые имеют другое назначение. Также следите, чтобы скобки были парными: для каждой открывающей скобки должна быть и закрывающая. При этом открывающие и закрываюшие скобки должны следовать правилу матрёшки. Если в скобках (внешних) есть другие скобки (внутренние), то они должны целиком находиться внутри внешних скобок. Операция возведения в степень выполняется справа налево! Результат вычисления арифметического выражения 2 ** 2 ** 3 равен не 64, а 256, в чём легко убедиться: 35
То есть сначала вторая двойка возводится в куб, а затем первая двойка – в восьмую степень. Если вы хотите возводить в степень слева направо, то используйте скобки: Приоритеты арифметических операций вы найдёте в таблице: Операции Действие Приоритет () Круглые скобки ** Возведение в степень + - Унарный плюс Унарный минус * / // % Умножение Вещественное деление Целочисленное деление Остаток от целочисленного деления 3 + - Сложение Вычитание 2 4 Арифметические операции с одинаковым приоритетом сгруппированы в строки одинакового цвета. Математические операции с вещественными числами К вещественным числам можно применять те же арифметические операции, что и к целым, но нужно учитывать особенности вычислений в Питоне: если в выражение входит хотя бы одно вещественное число, результат всегда вещественное число (Рис. 1). 36
Рис. 1 При целочисленном делении вещественных чисел результат – это целая часть частного, но вещественного типа. Дополнительные операции с числами В математике абсолютную величину числа обозначают двумя вертикальными чёрточками: |-2|. В Питоне так не получится – нужно использовать функцию abs, а в круглых скобках указать число. Функция возвращает абсолютную величину (модуль) этого числа (Рис. 1). Рис. 1 В школе изучают тригонометрические функции. Например sin x, cos x. sin и cos – это название функций. х – это аргумент функции. Обычно это угол в градусах или радианах. Тригонометрические функции есть и в Питоне. Важное отличие функций в Питоне от функций в математике: аргументы функций в Питоне всегда заключаются в круглые скобки: sin(0.5), cos(1). Углы здесь задаются в радианах. Математические функции возвращают значение вещественного типа – например, величину синуса или косинуса заданного угла. Теперь вы легко поймёте запись abs(-2). abs – это название функции, а в скобках записан аргумент – двойка – число, которое мы передаём функции. Функция возвращает результат её выполнения. 37
Функция divmod(x, y) возвращает пару чисел (кортеж). Первое число – целая часть частного от деления x // y. Второе – остаток от деления x % y (Рис. 2). Рис. 2 Кортеж в Питоне – это набор данных одного типа или разных типов. Данные перечисляются через запятую в круглых скобках. Функция pow(x, y) с двумя параметрами возвращает xy – число х в степени y (Рис. 3). Рис. 3 Легко заметить, что целочисленный результат точный, а вещественный округляется до 17 значащих цифр. Функция pow(x, y, z) с тремя параметрами возвращает xy % z, то есть остаток от деления степени xy на z (Рис. 4). Рис. 4 Вызовы функций выполняются раньше арифметических операций (Рис. 5). Рис. 5 38
То есть приоритет вызова функций выше, чем арифметических операций. Чтобы вызвать функцию, нужно записать её имя, а в скобках – аргумент или аргументы – через запятую. После выполнения функции в выражение подставляется возвращаемое значение. Выражение аbs(-2) ** 3 вычисляется так. Сначал выполняется вызов функции аbs(-2), котороая возвращает целое число 2 → арифметическое выражение принимает вид 2 ** 3, которое очень просто понять. Преобразование и приведение числовых типов В Питоне два основных числовых типа данных – целые и вещественные числа. Операция вещественного деления / возвращает вещественное число, если даже оба операнда целого типа. Если все операнды имеют целый тип и не используется операция вещественного деления, то результат операции целое число. Если хотя бы один операнд вещественного типа, то и результат будет иметь вещественный тип. В этом случае транслятор автоматически преобразует операнды целого типа к вещественному. Иногда нужно самостоятельно преобразовать операнд у другому типу. Такое преобразование типов называется приведением. Для приведения вещественных чисел к целому типу используйте функцию int (Рис. 1). Рис. 1 Функция int без параметров возвращает целочисленный нуль: 39
Эта функция умеет конвертировать строку в число (Рис. 2). Рис. 2 Но в строке должно быть записано правильное целое число, иначе программа завершится с ошибкой. Строка в Питоне – это последовательность символов, заключённая в двойные или одинарные кавычки. Строки имеют тип str (сокращение слова string строка): Строки – это нечисловой тип данных, поэтому их нельзя использовать в математических выражениях. Строки нужно либо конвертировать в числа, либо использовать функцию eval (см. дальше). По умолчанию функция int конвертирует строку в десятичное число, но функция int с двумя параметрами позволяет задать основание системы счисления для числа в строке (Рис. 3). Рис. 3 Для записи двоичных, восьмеричных и шестнадцатеричных чисел можно использовать префиксы. Основание системы счисления должно иметь значение в интервале 2..36 (Рис. 4). Рис. 4 Для приведения целых чисел к вещественному типу используйте функцию float (Рис. 5). 40
Рис. 5 Функция float без параметров возвращает вещественный нуль: Функция float умеет конвертировать строки, в которых записаны правильные целые или вещественные числа (Рис. 6). Рис. 6 Иногда нужно, наоборот, конвертировать целое или вещественное число в строку. Для этого служит функция str (Рис. 7). Рис. 7 В Питоне имеется функция eval, которая вычисляет выражение, записанное в строке, и возвращает результат (Рис. 8). Рис. 8 41
Обобщение 1. В интерактивной оболочке IDLE удобно выполнять арифметические вычисления. 2. Все числа в Питоне делятся на 2 основных типа – целые и вещественные. 3. В записи вещественных чисел обязательно должна быть десятичная точка, которая отделяет целую часть от дробной. В математике вместо точки используют запятую – не перепутайте! 4. Числа могут быть положительными и отрицательными. Перед отрицательными числами ставят знак минус. Перед положительными числами можно ставить знак плюс, но этого обычно не делают. 5. Арифметические операции делятся на бинарные и унарные. В бинарных операциях участвуют два числа, между которыми ставят знак арифметической операции: + - * / // ** %. Числа в арифметических операциях называются операндами. В унарных операциях участвует единственный операнд. Перед ним ставят знак операции. Это может быть унарный плюс или унарный минус: +2 -2. Унарный плюс обычно не ставят, а унарный минус ставят перед отрицательным числом обязательно. Он изменяет значение числа на противоположное. Приоритет унарных операций выше, чем у деления и умножения, поэтому отрицательные числа можно записывать без скобок (Рис. 1). Рис. 1 Деление – самая коварная арифметическая операция. Помните, что на нуль делить нельзя! Приоритет операции возведения в степень выше, чем унарных операций. Значение этого арифметического выражения равно -4, а не 4 (Рис. 2). Рис. 2 Сначала возводим двойку в квадрат: 22 = 4. Затем дописываем унарный минус 4 → -4. В математической записи это свойство арифметических операций видно более наглядно: -22 = 4. 42
6. Если в арифметической операции участвуют только целые числа и к ним не применяется операция вещественного деления, то результат операции – целое число. 7. Если в арифметическом выражении хотя бы одно число вещественное или применяется вещественное деление, то результат – вещественное число. 8. Порядок выполнения арифметических действий определяется приоритетами арифметических операций. Сначала слева направо выполняются операции с наиболее высоким приоритетом, потом – с более низким, и так далее. Операции возведения в степень выполняются справа налево. Операции Действие () Круглые скобки f(аргументы) Вызов функции ** Возведение в степень + - Унарный плюс Унарный минус * / // % Умножение Вещественное деление Целочисленное деление Остаток от целочисленного деления + - Сложение Вычитание 9. Изменить порядок выполнения операций можно с помощью круглых скобок. 10. Выражения в скобках вычисляются в соответствии с приоритетами операций. Если в выражении имеются вложенные скобки, то сначала выполняются действия в самых глубоко вложенных скобках. Затем переходят к следующим по вложенности скобкам и так далее: ((1) 3 (2)) 11. Знаки операций умножения *, возведения в степень **, вещественного деления /, целочисленного деления // и деления по модулю % отличаются 43
от математических. А скобки в арифметических выражениях должны быть только круглыми. 12. Косую дробную черту / иногда называют на английский манер слешем (читайте: слэшем). Рассмотрим примеры: Арифметическая операция 6+3 6-3 6*3 6/3 6 // 3 6%3 6 ** 3 (6 – 3) * -3 (2 + 4 - 1) / 5 * 11 (3.1415 – 1.0) / 7.78 * (45 - 7) -2.67 * 3.14 + -3/2 – 7.01 3 * 4 + 5 – 6/2 Результат 9 3 18 2.0 2 0 216 -9 11.0 10.459768637532136 -16.8938 14.0 13. Для приведения вещественных чисел к целому типу и конвертирования строк в целые числа используйте функцию int. 14. Для приведения целых чисел к вещественному типу и конвертирования строк в вещественные числа используйте функцию float. 15. Для конвертирования чисел в строки служит функция str. 16. Вызовы функций имеют более высокий приоритет, чем арифметические операции. 17. Функция abs возвращает абсолютную величину числа. 18. Функция divmod(x, y) возвращает целую часть частного от деления числа x на число y и остаток от деления x на y. 44
Задание для самостоятельного решения Числа и арифметические выражения встречаются практически в каждой программе, поэтому хорошенько потренируйтесь на вычислениях. Примеры вы найдёте в школьных учебниках. Но учитывайте различия между математикой и программированием. Особое внимание обращайте на тип результата – целый или вещественный. От этого зависит точность и надёжность ваших будущих программ. Старайтесь проверять свои «школьные» вычисления не по ответам в учебнике, а в программах на Питоне. В простых случаях для этого достаточно возможностей интерактивной оболочки IDLE. 45
Занятие_3. Практикум по вычислительным задачам С помощью простых арифметических действий уже можно решать интересные задачи. Давайте попробуем! Кошки-мышки Александр Альбов в занимательной и познавательной книге От абака до кубита. История математических символов (Рис. 1) приводит такую задачу из папируса Райнда: В семи домах сидят по семи кошек, и каждая поймала семь мышей. Сколько всего мышей они изловили? Рис. 1 Автор приводит «современный способ решения»: семь возвести в третью степень. Мы хорошо помним, что квадрат семи равен 49; осталось умножить 49 на 7 и получить 343. Египтянам приходилось семь раз сложить 7, зафиксировать результат 49 и семь раз сложить 49. 46
Египтянам приходилось несладко, а вот современным школьникам значительно легче. Если они, конечно, выучили таблицу умножения. А с Питоном и вычислять ничего не нужно. Достаточно записать арифметическое выражение и нажать клавишу ВВОД, чтобы получить ответ (Рис. 2). Рис. 2 Вы знаете, что функция pow возводит первый аргумент в степень, заданную вторым аргументом. Александр Альбов предлагает нам именно этот способ. Возведение в степень в математике записывают так: 73. В Питоне и в других языках программирования для этого используют функции (Рис. 3). Рис. 3 В Питоне имеется замечательная операция возведения в степень, которой пользоваться гораздо удобнее, чем функцией pow (Рис. 4). Рис. 4 Шахматная задача Вам, возможно, известна легенда об изобретателе шахмат, которого правитель Индии, царь Шерам решил отблагодарить за интересную игру и предложил ему самому назначить цену. Изобретатель - его звали Сета - попросил заплатить ему зерном. А зёрнышки посчитать так: На первую клетку шахматной доски положить 1 зерно пшеницы, на вторую 2, на третью 4, на четвёртую 8, и так далее, каждый раз увеличивая число зёрен в 2 раза. 47
И легенда, и задача встречаются во многих книгах по занимательной математике. Например, вы можете прочитать о ней в книге В. Литцмана Великаны и карлики в мире чисел, на странице 26. На первый взгляд кажется, что в итоге получится всего горстка пшеницы. Так подумал и царь Шерам и приказал выдать скромному изобретателю гораздо больше – целый мешок пшеницы. Но тот попросил отмерить ровно столько зёрен, сколько получится в результате вычислений. Шерам не стал спорить с изобретателем и повелел точно вычислить, сколько тому причитается зёрен. Когда придворные математики закончили свои долгие вычисления, то оказалось, что зёрен должно быть так много, что их просто не могло быть ни у Шерама, ни у кого другого на земле. Если отбросить «мелкие подробности», то нам нужно найти сумму чисел: 20 + 21 + 22 + 23 + 24 + … + 263 Эти числа образуют геометрическую прогрессию. Сумма её членов равна 264 – 1. При помощи операции возведения в степень мы без труда решим знаменитую шахматную задачу. На бумаге это трудное и долгое занятие, а вычислить сумму членов геометрической прогрессии на Питоне можно за несколько секунд. 48
В интерактивной оболочке запишите выражение для суммы членов геометрической прогрессии на питоньем языке, нажмите клавишу ВВОД и получите ответ на задачу (Рис. 1). Рис. 1 Число огромное, а мы нашли его за одно мгновение! Применяем «функциональный» способ вычислений (Рис. 2). Рис. 2 В книге Перельмана Живая математика вы можете прочитать эту легенду, откуда заодно узнаете, что число называется: восемнадцать квинтильонов четыреста сорок шесть квадрильонов семьсот сорок четыре триллиона семьдесят три биллиона семьсот девять миллионов пятьсот пятьдесят одна тысяча шестьсот пятнадцать Якобы так его назвали придворные математики, согласно легенде. Число верное, но квинтильоны и квадрильоны появились гораздо позже. Опять же согласно легенде, царь не смог сдержать своего обещания, но в книге вы найдёте хитроумный способ выполнить его и тем самым не уронить своего царского достоинства. Вы хотите узнать как? – Тогда читайте книгу! 49
Число шахматных партий Ещё одна задача, тесно связанная с шахматами. В книге Перельмана Занимательная алгебра рассматривается вопрос о приблизительном подсчёте всех возможных шахматных партий. При этом автор пользуется способом бельгийского математика М.Крайчика, изложенным в книге Математика игр и математические развлечения. Я не буду пересказывать содержание книги Перельмана, а сразу оглашу результат: (20 x 20)5 x (30 x 30)35 Дальше идут трудоёмкие вычисления, которые нам не нужны, потому что для Питона эти вычисления – детская задача (Рис. 1). Рис. 1 Это число точное, хотя число партий приблизительное. В книге Перельмана приводится более грубая оценка: 2 х 10116. Если вы не поленитесь и пересчитаете все цифры в полученном числе, то их окажется 117 штук. То есть результат в книге Перельмана верный, но округлённый. Только не подумайте, что я воспользовался своим же советом и добросовестно пересчитал цифры. Питон и здесь всё сделает за нас, если его правильно попросить (Рис. 2). Рис. 2 50
Какая разница? Бен Орлин в книге Math with Bad Drawings. Illuminating the Ideas That Shape Our Reality (Рис. 1) приводит показательный пример математического взгляда на вещи. Рис. 1 Для людей, далёких от математики, выражения x2 и 2x отличаются только переменой мест буквы х и цифры 2, то есть незначительно. А математики знают, что разница между этими выражениями огромная. Если х = 10, то значение первого выражения равно (Рис. 2). Рис. 2 А второго? – Гораздо больше (Рис. 3). Рис. 3 Про быстрое возрастание степеней числа 2 вы уже знаете по шахматной задаче. А Бен Орлин приводит подобный пример для х = 100 (Рис. 4). 51
Рис. 4 Если первое число всё ещё относительно небольшое, то второе – огромное! Если первое число можно сравнить с весом грузового автомобиля (в фунтах), перевозящего кирпичи, то второе число – это вес ста тысяч Земель. Складывание бумаги Как иногда удивительным образом стародавние задачи появляются в новом обличии! Казалось бы, вполне современная головоломка со складыванием листа бумаги не имеет с шахматной задачей родственных связей, но это не так. Обе поражающие воображение задачи основаны на свойствах показательной функции. В 28-ом математическом выпуске Академии занимательных наук профессор Круглов наглядно доказывает хомячку Циркулю, что лист бумаги формата А4 нельзя сложить вдвое более 6 раз (Рис. 1). Рис. 1 52
Но в Интернете можно найти ролик, в котором показано, как такой же лист бумаги можно сложить 7 раз (Рис. 2). Рис. 2 Фокус в том, что сначала листок нужно складывать по длинной стороне, а не попеременно по длинной – по короткой. Нашлись умельцы, которые взяли огромный лист бумаги и свернули его 9 раз (Рис. 3). Рис. 3 53
В ролике Разрушители легенд. Сложить бумагу больше 7 раз, который вы найдёте на Ютубе, разрушительная тройка самозабвенно пытается крепко смять бумагу более 7 раз (Рис. 4). Рис. 4 Давайте разбираться, почему бумага так упорно не желает складываться вдвое! Так как мы не проводим натурные испытания, то удовольствуемся простой математической моделью процесса складывания бумаги вдоль и поперёк. Она несущественно упрощает этот процесс, зато описывается элементарной формулой: d = a · 2n d – общая толщина сложенного листа бумаги а – толщина самого листа n – число складываний Возьмём достаточно тонкую бумагу толщиной a = 0.1 мм. В начале эксперимента весь «свёрток» имеет такую же толщину (Рис. 5). Рис. 5 54
Пока всё нормально. После трёх складываний толщина сложенного листа бумаги всё ещё меньше 1 миллиметра (Рис. 6). Рис. 6 Но при последующих складываниях толщина листа стремительно растёт (Рис. 7). Рис. 7 После 9 складываний толщина достигнет 5 сантиметров, а после 12 – почти 410. Теперь легко представить размеры исходного листа бумаги, чтобы его можно было сложить пополам при такой толщине. Если конечная площадь верхней поверхности листа 40 квадратных сантиметров, то исходный лист при 12 складываниях должен быть в 4096 раз больше, то есть 163840 квадратных сантиметров, или 16,4 квадратных метра. На самом деле площадь исходного листа должна быть значительно больше, поскольку мы складываем не отдельные листы стопкой, а единственный лист, часть которого образует боковые поверхности. Также мы предполагаем, что лист размером 40 х 80 сантиметров толщиной 40 сантиметров ещё можно сложить вдвое. 55
Но если 12 раз сложить вдвое огромный лист тонкой (!) бумаги ещё вполне возможно, то дальше толщина листа измеряется метрами (Рис. 8). Рис. 8 Для удобства вычислений мы запоминаем результаты математических операций в переменных n и d. О переменных подробно поговорим на Занятии_5. Здесь мы наблюдаем ту же самую картину, что и при выкладывании зёрен на шахматную доску. Толщина листа бумаги растёт так быстро, что даже 15 складываний проделать не удастся. В книге Вальтера Литцмана Великаны и карлики в мире чисел, пятое издание которой вышло в Лейпциге в 1953 году, эксперимент со складыванием бумаги приводится как пример быстрого роста показательной функции. При складывании листа бумаги толщиной 1/10 мм 40 раз высота «стопки» превысит 100 000 километров! 56
Три цифры - раз Яков Перельман в книге Занимательная арифметика (Рис. 1) предлагает решить Задачу №58: Какое самое большое число можно написать тремя цифрами, не употребляя никаких знаков действий? Рис. 1 В качестве цифр хочется использовать три девятки – и этот выбор правильный. Второй шаг – верно составить из этих девятое число. Например, так (Рис. 2). Рис. 2 57
Возможно, вы придумаете и другие способы для записи чисел, но всё равно самое большое число, которое можно записать тремя девятками, - это (Рис. 3). Рис. 3 То есть 9 в степени 9 в степени 9. Чтобы было легче соображать, вычислим степень 99 (Рис. 4). Рис. 4 Тогда исходное выражение можно записать так: 9387420489 = ??? Если все предыдущие расчёты легко выполнить на Питоне (что я и сделал), то последнее число даже не пытайтесь вычислять! Оно состоит из 369 693 100 цифр, так что напечатать его вряд ли удастся. А если и удастся, то пользы от него – никакой. Более подробно об этом числе вы можете прочитать в указанной выше книге. 58
Три цифры - два Эта задача нашла продолжение в другой книге Перельмана – Занимательная алгебра (Рис. 1). Но здесь задачи проще. Рис. 1 В первой задаче требуется, не употребляя знаков действий, записать тремя двойками наибольшее число. «Подвох» задачи заключается в невольном переносе решения задачи с девятками на задачу с двойками. Но получается (Рис. 2) Рис. 2 совсем небольшое число (Рис. 3). 59
Маловато будет! Рис. 3 Даже «простое» число 222 заметно больше. Следующий претендент на лавры победителя – число 222 (Рис. 4). Рис. 4 Но и оно сравнительно невелико. А правильный ответ такой (Рис. 5). Рис. 5 Во второй задаче место двоек занимают тройки. Здесь двухэтажная степень (Рис. 6) даёт хороший результат (Рис. 7). Рис. 6 Рис. 7 Но не лучший! А побеждает опять одноэтажная степень (Рис. 8). 60
Рис. 8 В этой задаче можно обойтись вообще без вычислений, если заметить, что 3 в кубе – это 27, то есть показатель степени в первом случае меньше, чем во втором (33). Третья задача продолжает этот ряд, и теперь нужно составить наибольшее число из трёх четвёрок. Так как 44 = 256, то двухъярусная степень значительно больше одноярусной с показателем степени 44 (Рис. 9). Рис. 9 Читая книгу дальше, вы узнаете, почему для чисел 2 и 3 выгоднее одноярусная степень, а для больших - двухъярусная. История с тремя одинаковыми цифрами продолжилась в интересной математической книге для школьников (Рис. 10). Рис. 10 61
На странице 30 дана для ручных вычислений вот такая задача (Рис. 11). Рис. 11 Здесь почему-то авторы книги нарушили логику и вместо числа 44 употребили число 40. Впрочем, суть задачи от этого не пострадала (Рис. 12). Рис. 12 Гугол Число, которое изображается единицей с сотней нулей, называется гуголом: 10 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 Мы легко получим его в интерактивной оболочке (Рис. 1). Рис. 1 62
Но интересно происхождение названия этого числа. Его придумал не математик, а племянник американского математика Эдварда Каснера в 1938 году. Племянника звали Милтон Сиротта, и тогда ему было 9 лет. Эдвард Каснер прогуливался со своими племянниками по парку, и речь у них зашла о числе, у которого 100 нулей. Число такое большое, что им нечего обозначать. Именно поэтому оно не имело собственного названия. Маленький Милтон предложил назвать его гуголом. В 1940 году Эдвард Каснер и Джеймс Ньюмен написали книгу Mathematics and the Imagination (Математика и воображение) (Рис. 2), в которой и рассказали об этом числе. Вот так это число получило своё имя! Рис. 2 По-английски название гугол пишется как googol. Название известной поисковой машины и компании Google произошло от названия этого числа. А правильное математическое название этого числа: десять дуотригинтиллионов или десять седециллиардов. 63
По той же легенде, племянник придумал название гуголплекс (googolplex) для числа, у которого гугол нулей после единицы. Понятно, что это название – просто курьёз, потому что в природе нет ничего, что можно было бы обозначить таким числом. Задача Рачинского На картине русского художника Николая Петровича Богданова-Бельского Устный счёт. В народной школе С. А.Рачинского (1895) вы можете видеть интересное арифметическое выражение (Рис. 1). Рис. 1. Картина и арифметический пример В журнале Наука и жизнь, № 7 за 2006 год, на страницах 50-51 обсуждаются способы устного решения этой задачи. Задача легко решается, если догадаться, что сумма трёх первых квадратов равна сумме двух последних и равна … вы уже догадались чему? Если не догадались, то давайте вычислим эти суммы на Питоне (Рис. 2). Рис. 2 64
Теперь задачу легко решить и в уме – получается двойка (не опять двойка, а просто двойка!) В книге Перельмана Занимательная алгебра вы найдёте доказательство, что имеется ещё одна последовательность из 5 чисел, обладающая таким же свойством: сумма квадратов первых трёх чисел в точности равна сумме квадратов последних двух чисел. Но эта последовательность совершенно неинтересная: -2, -1, 0, 1, 2 Иногда эту задачу обобщают, то есть не ограничивают длину последовательности. Такие ряды чисел называются последовательностями Рачинского. Они состоят из квадратов идущих подряд чисел, которые можно разбить на 2 группы с равными суммами так, что во второй группе на 1 число меньше, чем в первой: 32 + 42 = 52 = 25 212 + 222 + 232 + 242 = 252 + 262 + 272 = 2030 362 + 372 + 382 + 392 + 402 = 412 + 422 + 432 + 442 = 7230 Проверьте эти равенства на компьютере! Вычисление сложных арифметических выражений Как вы уже знаете, арифметические действия выполняются согласно их приоритетам. Старшинство скобок самое высокое. Затем идёт возведение в степень, а после него умножение, деление и деление по модулю. В последнюю очередь выполняют действия сложения и вычитания. Действия с одинаковым приоритетом выполняются последовательно слева направо (кроме возведения в степень). Понятно, что Питон сумеет вычислить любые арифметические выражения, которые задают в школе, поэтому придумаем для него задание сложнее: (67 + 7 * 23) + 23**4 – 222 * 12 В программировании, как и в математике, не принято целиком вычислять длинные, сложные выражения, поэтому будем вычислять по частям. 65
Для выражения в скобках (67 + 7 * 23) последовательность действий такая: 1. Двойку возводим в куб. Получаем 8 2. 7 умножаем на 8. Получаем 56 3. Находим сумму чисел 67 и 56. Получаем 123 Всё верно (Рис. 1). Рис. 1 Выражение 23**4 самое сложное. Я даже не смог правильно записать его в текстовом редакторе. Здесь нужно выполнить 2 возведения в степень. Как вы уже знаете, возведение в степень выполняется справа налево. Вычисляем выражение 222 * 12: 1. Возводим 22 в квадрат. Получаем 484 2. Умножаем 484 на 12. Получаем 5808 Тоже всё верно (Рис. 2). Рис. 2 Теперь можно вычислить и всё выражение целиком (Рис. 3). Рис. 3 Обобщение 1. С помощью Питона можно легко решить любые вычислительные задачи. Это сделать гораздо проще, чем на бумаге. При этом результат всегда получится верным, потому что Питон не делает ошибок (а вот вы вполне можете наделать ошибок и на компьютере!). 2. Не нужно решать на компьютере все задачи подряд. Нужна тренировка и в «бумажных», и в умственных упражнениях. В таких случаях правильнее использовать компьютер для проверки своих вычислений. 66
3. Трудоёмкие вычисления, конечно, лучше сразу выполнять на компьютере. Так вы сможете решить множество интересных математических задач, которые при ручном решении превращаются в мучение и отвращают от математики. Всё-таки математика – это красивая наука для ума, а не тяжкий труд для рук. 67
Занятие_4. Грамматика Питона Аз да буки, а там и науки. Русская пословица Мама мыла раму. Классическая фраза из букваря Исходный код программы на Питоне - это обычный текст, состоящий из слов, чисел и различных знаков. Поскольку мы набираем его с клавиатуры, то в программе и не может быть никаких других символов, кроме тех, что имеются на стандартной клавиатуре. Зато почти все символы на клавишах используются в программах: • Все строчные и прописные буквы как латинского, так и русского алфавита, а также знак подчёркивания _ и пробел. • Все цифры. • Специальные символы: # % ' " ( ) * * + , - . / // : < = > [ ] { }. Из цифр можно составить числа - целые и действительные (числа с плавающей точкой, вещественные). Обычно их записывают в привычном для нас десятичном виде, но в программировании часто используют двоичную и 16-ричную запись целых чисел. Двоичные числа состоят только из двух цифр – 0 и 1. Чтобы отличать двоичные числа от десятичных, перед двоичными числами ставят префикс 0b (цифра ноль и латинская буква b): 0b0001 0b0111 0b1111 В IDLE мы легко узнаем, чему равно двоичное число в десятичной системе счисления (Рис. 1). Рис. 1 68
16-ричные числа записываются с помощью цифр 0..9 и латинских букв A..F (или a..f). Перед такими числами должен стоять префикс 0x: 0x0A 0x20 0xFFFFFFFF И опять нам на помощь приходит среда разработки (Рис. 2). Рис. 2 Для восьмеричных чисел достаточно обычных цифр, но их легко спутать с десятичными, поэтому перед числами в восьмеричной системе ставят префикс 0o (ноль и латинская буква o): 0o2022 0o77 0o1234567 Нам осталось узнать, что это за числа в десятичной системе (Рис. 3). Рис. 3 Очень большие и очень маленькие действительные числа иногда записывают в научной нотации: 1.5e8 (1.5E8), что составляет 150 000 000 (расстояние от Земли до Солнца в километрах) (Рис. 4). Рис. 4 69
Сначала записывают вещественное число, затем латинскую букву е или Е и показатель степени десятки, то есть число нулей: 1.5e8 = 1.5 * 108 = 150 000 000. Из букв, цифр и знака подчёркивания можно составить константные выражения и задать имена переменным, константам, функциям и классам. Расстояние от Земли до Солнца приблизительно равно 150 000 000 км. Число длинное, поэтому в нулях легко запутаться. В книгах длинные числа разбивают на группы по 3 цифры, начиная с конца, а группы разделяют пробелом. В Питоне пробел между цифрами ставить нельзя. Для этого используется разделитель цифр - знак подчёркивания, который можно вставлять в любое место числа (числового литерала). Двоичные числа обычно разбивают на тетрады – группы по 4 бита: 0b0001_0000 0b1111_1001 Целые десятичные числа разбивают на группы по 3 цифры: 150_000_000 Расстояние в километрах до ближайшей звезды (Солнце мы уже посчитали) Проксимы Центавра равно: 39_900_000_000_000 Разделитель можно использовать и в вещественных числах. Известная вам функция int преобразует строку, в которой записано правильное целое число в десятичной системе, в целое число типа int. Если число в строке записано неверно, то программа выдаст ошибку (Рис. 5). 70
Рис. 5 Дополнительно можно указать любую систему счисления от 2 до 36 для перевода строки с десятичным числом. Если основание системы счисления задано неверно, то программа выдаст ошибку (Рис. 6). Рис. 6 В десятичной системе счисления 10 разных цифр. В 11-ричной системе 11 цифр. В 12-ричной – 12, и так далее. Если основание больше десяти, то вместо цифр используются буквы латинского алфавита. Таких букв всего 26, поэтому максимальное основание, в котором можно записывать любые числа, равно 10 + 26 = 36. Функция bin возвращает строку, в которой записано строковое представление заданного десятичного числа в двоичной системе (Рис. 7). Рис. 7 Функция oct возвращает строку, в которой записано строковое представление заданного десятичного числа в восьмеричной системе (Рис. 8). Рис. 8 71
Функция hex возвращает строку, в которой записано строковое представление заданного десятичного числа в 16-ричной системе (Рис. 9). Рис. 9 Выражения Из чисел и арифметических знаков можно составлять выражения: 1 + 2 2 * 2 3 * 4 + 5 – 6/2 -12 -2.67 * 3.14 + -3/2 – 7.01 Между числами и знаками арифметических операций может быть любое число пробелов, но допустимо печатать их и вплотную друг к другу. Правильно записывать выражения нужно так: вставлять ровно 1 пробел до и после знака операции. Унарный минус записывают вплотную к числу. Выражения могут состоять не только из чисел, но также из идентификаторов переменных, вызовов функций и круглых скобок. Идентификаторы Как вы судно назовёте, так оно и поплывёт. Ной Если мы хотим обратиться к человеку, то должны знать его имя (в особо ответственных случаях - имя, отчество и фамилию). Так и в Питоне – объекты не могут обходиться без имени, которое называется идентификатором. Идентификатором может служить любая последовательность букв и цифр, начинающаяся с буквы или знака подчёркивания. Таким образом, _i 72
abcd qwerty i_j g56 o8j90 это правильные имена для любых объектов программы. Но они годятся только в качестве кодов к замкам, потому что не имеют никакого смысла, доступного человеческому разумению. В Питоне строчные и ПРОПИСНЫЕ буквы считаются различными, поэтому идентификаторы python Python PYTHON PYthon обозначают разные объекты! Ключевые (зарезервированные) слова Питон даёт нам полную свободу словотворчества, поэтому мы можем в качестве идентификаторов использовать любые слова, которые знаем или можем придумать. Запрещено использовать не по прямому назначению только зарезервированные слова: True False None and as asset break class continue def del elif else enum except finally for from global if import in is lambda nonlocal not or pass raise return try Красным цветом выделены константы, которые используются иначе, чем остальные ключевые слова. 73
Как правильно выбрать имя Разработчик программы должен сам позаботиться о том, чтобы идентификаторы объектов были не только правильными, с точки зрения языка Питон, но и подсказывали ему тип объекта и его назначение в программе. Идентификаторы по-венгерски, по-паскальски, поверблюжьи и по-русски Плохие идентификаторы, как и плохие имена, затрудняют жизнь программ и людей. Чтобы облегчить выбор, сотрудник фирмы Майкрософт Чарльз Силош предложил заковыристую систему составления имён объектов программы. Как известно, венгерский язык очень сложный, но «венгерской» эту систему прозвали не поэтому - просто Чарльз Силош по происхождению венгр. Существует немало разновидностей этой системы, но мы остановимся на самой простой и внятной из них. Итак, «по-венгерски» любой идентификатор составляют из двух частей: • префикса, записанного строчными буквами, который указывает тип объекта, и • спецификатора, начинающегося с ПРОПИСНОЙ буквы. Например, префикс i обозначает целый тип int. Тогда координаты точки на экране можно хранить в двух переменных: iX, iY или iXCoord, iYCoord или iCoordX, iCoordY Если имеется в виду не точка, а мяч, то идентификатор легко приспособить и к этому случаю: iXBall, iYBall Префикс может также отражать назначение объекта: c (counter) – счётчик cur (current) – текущее значение f, flg (flag) – переменная логического типа p, ptr (pointer) – указатель n, num (number) – число, количество чего-либо 74
tmp (temporal) – временное значение Вы можете выработать свою систему наименования, но некоторые распространённые префиксы желательно при этом учитывать. Префикс Объект b, flg переменная логического типа bool i переменная целого типа int lst список x, y, z dx, dy координаты приращение координат id, idx индекс, идентификатор s, str строка Этот список вы можете продолжить сами. В современном программировании префиксы практически не используют. Идентификаторы констант обычно записывают ПРОПИСНЫМИ буквами, разделяя отдельные слова знаком подчёркивания: MAX_WIDTH = 20; MAX_HEIGHT = 24; В Питоне констант нет, поэтому эти идентификаторы только сигнализируют программисту, что значения таких переменных изменять нельзя. В Питоне все идентификаторы переменных и функций должны начинаться со строчной буквы: hello program main Если идентификатор состоит из нескольких слов, то они разделяются знаком подчёркивания: hello_world my_program main_func 75
Можно использовать и верблюжий стиль: первое слово пишется со строчной буквы, а все последующие – с прописной: myFirstProgram mainProgramMethod Достаточно посмотреть на двугорбого верблюда, чтобы понять смысл названия этого стиля! Имена классов начинаются с прописных букв: Hello Program Main Если имя класса состоит из нескольких слов, которые пишутся слитно, то каждое из них должно начинаться с ПРОПИСНОЙ буквы, а все остальные буквы слова должны быть строчными: HelloWorld MyProgram MainFunc Такой способ конструирования имён называется стилем паскаля. В Питоне разрешается использовать русские слова не только в комментариях, но и для именования переменных и прочих объектов программы. Старайтесь не злоупотреблять этой возможностью, поскольку вам придётся постоянно переключаться с «латинской» раскладки клавиатуры на отечественную, ведь все ключевые слова Питона всё равно придётся писать латиницей. Если же вы захотите поделиться исходным кодом своей программы с другими пользователями, то велика вероятность того, что ваши идентификаторы превратятся в абракадабру, которую никто понять не сможет. Конечно, идентификаторы лучше записывать латинскими буквами. С другой стороны, не каждый ведь знает английский язык, поэтому можно записывать русские слова латинскими буквами, как это принято делать в Интернете. Вы можете использовать и свою систему перевода, главное, чтобы она была единой во всех ваших проектах. 76
Идентификаторы в Питоне могут быть очень длинными. Например, qwertzuiopasdfghjklyxcvbnm1234567890, поэтому не жалейте букв! Главное – чтобы идентификатор ясно говорил о назначении объекта. Комментарии Комментарии должны описывать алгоритм, а не элементарные действия, которые и без того всем понятны. Например, комментарий ничего не объясняет, а просто пересказывает действие оператора сложения. Комментарий уже значительно лучше, поскольку мы понимаем, что в этом месте кода подсчитывается количество слов, а не абстрактных объектов. Однострочные комментарии начинаются со знака #, за которым следует пробел и собственно комментарий. Однострочный комментарий можно помещать в конце строки кода или на отдельной строке: 77
И тогда комментарии занимают целиком всю строку либо остаток строки. Когда вы только пишете программу, вам и без комментариев всё в ней понятно. Но если вам понадобится модифицировать (изменить) программу, написанную несколько месяцев назад, вот тогда и начнутся проблемы: без комментариев придётся восстанавливать весь алгоритм заново, а это иногда бывает труднее, чем с начала придумать новый. Не меньше трудностей вы создадите и своим коллегам, если поделитесь с ними своей программой. Вряд ли им доставит удовольствие многочасовой разбор «немого» кода. Ещё больше вы сможете насолить им и себе, если будете называть объекты малопонятными именами. Не жалейте времени на комментирование программы. Тогда вы и сами легко разберётесь в коде, и другие программисты будут вспоминать вас с благодарностью. А вот компилятор комментарии просто игнорирует, так что от ваших пояснений выполняемый код не увеличится ни на один байт. Многострочный комментарий действует на несколько строк, заключённых в тройные апострофы: Если при отладке программы вам понадобится временно исключить из программы часть кода, то закомментируйте его символами ''' ''', как многострочный комментарий. Вернуть код к жизни очень просто – уберите символы комментария. Если вы хотите разделить длинную программу на отдельные смысловые составляющие, то начинайте строку со знака #, как комментарий, а затем первую и последнюю строку заполните знаками равенства, звёздочками или тире. В остальных строках ЗАГЛАВНЫМИ буквами напишите название раздела или всей программы: Можно добавить пустые строки, чтобы ещё больше выделить название: 78
Если надпись длинная, то её можно оформить как многострочный комментарий: Так заголовок будет выделен ещё лучше. Здесь же можно добавить пояснения о назначении программы. Сведём всю информацию о комментариях в компактную таблицу: Тип Однострочный комментарий Назначение Пример Используется в отдельной # комментарий строке или после оператора Многострочный комментарий Используется для нескольких ''' соседних строк Комментарий1 Комментарий2 ''' Обобщение Идентификаторы должны отражать, в первую очередь, назначение объектов в программе. Идентификаторы переменных и функций состо- 79
ят из строчных букв и цифр. Идентификаторы классов начинаются с прописной буквы. Если имя переменной или функции состоит из нескольких слов, то они записываются строчными буквами и разделяются знаком подчёркивания. Либо все последующие слова начинаются с прописной буквы. Этого правила следует придерживаться и при именовании классов, но тогда и первое слово должно начинаться с прописной буквы. Комментарии должны подробно объяснять алгоритм работы программы, поэтому основную часть комментариев обычно пишут до разработки исходного кода, который, по сути, и является переводом алгоритма на язык программирования. Однострочные комментарии начинаются со знака # и пробела. Многострочные комментарии начинаются с трёх апострофов и ими же и заканчиваются. 80
Занятие_5. Переменные и константы Чтобы передать привет, нужно заключить сообщение в парные двойные или одинарные кавычки (Рис. 1). Рис. 1 Большой недостаток таких «приветов» в том, что пользователь не может указать адресата своего послания, поэтому мы трижды писали строки, чтобы передать привет России, Питону и Миру - каждому в отдельности. В Питоне есть замечательная функция input, которая возвращает строку, которую пользователь ввёл с клавиатуры. Давайте посмотрим, как она работает. Чтобы вызвать функцию, нужно записать её имя и пару круглых скобок. После этого нужно ввести любую строку (слово, предложение, число, …) и нажать клавишу ВВОД. После выполнения «программы» будет напечатана строка, которую мы ввели, но уже в кавычках (Рис. 2). Рис. 2 Вызов функции input без аргументов (скобки-то пустые!) непонятен пользователю, который не знает, что от него ждёт программа. В таком случае мы можем записать в скобках строку, которая поясняет назначение этой функции. Например, так (Рис. 3). Рис. 3 Теперь программа знает, кому передать привет, но не знает, как это сделать, поскольку строка вывода не сохранилась, а просто напечатана на экране. И здесь на помощь приходят переменные. Переменные – это объекты программы, которые хранят информацию. В переменной можно, например, сохранить введённую строку. 81
У переменной должно быть имя (идентификатор), по которому мы сможем к ней обращаться. Это вы уже знаете. Пусть наша переменная называется komu. Также переменная имеет значение и тип. Тип переменной определяется её значением. Мы хотим сохранить в переменной komu строку, поэтому переменная получит строковый тип. Чтобы присвоить значение переменной, нужно выполнить операцию присваивания. Слева записываем имя переменной, затем знак равенства, а после него значение переменной: имя_переменной = значение Знак равенства называется оператором присваивания. Операцию присваивания начального значения переменной также называют её инициализацией. После выполнения операции присваивания переменная получает значение. Если мы укажем в программе имя переменной, то вместо неё будет подставлено её текущее значение. Из этого следует, что нельзя использовать в программе переменные, не получившие значения (не инициализированные). Теперь мы запросто присвоим переменной komu любое допустимое значение. Это может быть строка. Тип переменной – str, то есть строка, а значение - 'России' (Рис. 4). Рис. 4 Мы можем присвоить переменной значение, которое возвращает функция input (Рис. 5). Рис. 5 Как вы видите, текущее значение переменной komu – это введённая пользователем строка. Значение переменной мы можем использовать в программе. Пишем 'Привет' и прибавляем к этой строке переменную (Рис. 6). 82
Рис. 6 Этот пример показывает, что 2 строки можно складывать. Эта операция называется сложением, или конкатенацией строк. Оператор сложения строк точно такой же, как для чисел, - это знак плюс. Результат операции сложения строк – это строка, которая составлена из строк-слагаемых. Пробел между отдельными строками автоматически не вставляется, поэтому наш привет оказался всмятку. На ошибках учимся (Рис. 7). Рис. 7 Переменные могут изменять своё значение, поэтому они так и называются. Чтобы изменить значение переменной, нужно присвоить ей другое значение (Рис. 8). Рис. 8 Операция конкатенация стала универсальной: 'Привет ' + komu Нам не нужно её изменять, достаточно изменить значение переменной komu. Теперь вы запросто сможете передавать приветы направо и налево, просто изменяя значение переменной komu (Рис. 9). Рис. 9 И всё это стало возможным благодаря переменной komu. Как мы выяснили, эта переменная – строковая, и она умеет хранить любой текст. 83
Но есть переменные и других типов, которые также пригодятся нам в дальнейших программах. Переменные Как вы убедились, для хранения данных в программе нужны переменные. Они позволяют программе получать и сохранять информацию от пользователя, операционной системы или устройств ввода (например, мышки или клавиатуры). Когда вы запускаете какую-либо программу, она копируется в оперативную память компьютера и при работе выделяет для каждой переменной участок памяти, состоящий из нескольких смежных ячеек. В них и хранятся значения переменных (в двоичном виде, а совсем не так, как мы пишем в исходном коде). Итак, переменная представляет собой область памяти компьютера, в которой хранится её значение. Из этого следует, что каждая переменная имеет свой адрес в памяти, по которому её можно найти. Однако, в языке Питон не принято обращаться к переменным по их адресам. Адрес переменной знает программа, но не программист. Программист должен писать безопасный код, который не изменяет непосредственно содержание памяти компьютера. С другой стороны, мы должны как-то обращаться к нашим переменным. Для этого переменные имеют своё собственное имя (идентификатор). Мы уже использовали переменную komu. С одним вопросом мы разобрались: у всех переменных должно быть имя. Второй вопрос: откуда берутся переменные? – Ответ ясен: их должен ввести (определить) программист. При этом он указывает имя переменной и присваивает ей значение. Например, переменную komu можно определить так: komu = '' Здесь мы указываем компилятору, что собираемся хранить в этой переменной строку, а не число и не другие данные. При инициализации переменная komu может получить любое допустимое значение. Если вы пока не решили, какое именно значение должна иметь переменная, то 84
просто напечатайте пару кавычек. Тогда переменная получит строковое значение – пустую строку, в которой нет ни одного символа. Образно переменную можно представить как отдельную коробочку с текущим значением. На каждой коробочке написано имя переменной, а в коробочке хранится её значение. Когда Питон выполняет программу и встречает имя переменной, он находит коробочку и достаёт из неё значение, которое использует в программе. Всё просто и удобно: мы кладём в коробочку нужное значение, а программа достаёт его оттуда. Константы Константы в программировании разделяют на 2 вида – именованные и неименованные (их называют также явными константами, или литералами). Именованные константы сходны с переменными – они также могут хранить данные разных типов. Но константы не могут изменять своего значения. Как и переменные, мы можем представлять константы, как коробки, в которых хранятся значения констант. Но в коробку можно положить значение только 1 раз, после чего коробка закрывается на замок, и в неё уже ничего нельзя положить. А вот получать содержимое коробки (значение константы) можно сколько угодно раз. Именованные константы В Питоне именованные константы отсутствуют. По необходимости их заменяют переменными, но переменные могут изменять своё значение. Чтобы отличать константы-переменные от простых переменных, идентификаторы констант записывают ПРОПИСНЫМИ буквами. Если имя константы состоит из нескольких слов, то их разделяют знаком подчёркивания. Естественно, переменная не превратится в константу, если её имя записать иначе, поэтому программисты записывают имена констант прописными исключительно для себя – чтобы случайно не изменить значения констант-переменных в программе. Компилятор не выдаст 85
ошибку, если значение константы будет изменено. Поэтому будьте осторожны и внимательны, когда используете константы-переменные в своих программах. Пусть нам нужно написать программу, играющую в шашки. Доска имеет 8 вертикалей и 8 горизонталей. Если в исходном коде использовать числа, то эти восьмёрки невозможно отличить от других восьмёрок, которые тоже могут оказаться в коде. Да и вообще число 8 никак не указывает на то, что это число вертикалей на шахматной доске. Пусть нам удалось написать программу для игры в обычные шашки. Но потом мы решили взяться за 100-клеточные шашки, а там доска больше: 10 горизонталей и столько же вертикалей. Придётся просматривать (и очень внимательно!) весь код и исправлять восьмёрки на десятки. Конечно, лучше сразу описать две константы: MAX_ROW = 8 MAX_COL = 8 Если значения констант равны, то их можно описать в одной строке: MAX_ROW = MAX_COL = 8 То же самое относится и к описанию переменных Их же следует использовать и в тексте программы, тогда при переходе от русских шашек к международным достаточно изменить только 2 числа в самом начале программы, где их отыскать совсем нетрудно: MAX_ROW = MAX_COL = 10 Естественно, после этого программа не сможет играть в международные шашки! Речь идёт только о размере доски, а алгоритм игры изменится до неузнаваемости. 86
Литералы Литералы не нужно объявлять, они не имеют имени (поэтому их называют также неименованными константами), но имеют тип и значение. Например, все числа - это числовые константы (числовые литералы). Из чисел, знаков операций и круглых скобок можно составлять константные выражения: 123 240 + 12 Точно так же из любых символов можно составить строковые константы (любое количество любых символов, в том числе и ни одного). Строковые константы заключаются в одинарные или в двойные кавычки. Строковые константы: "Python" "G" "Constant" "Строковая константа" "" – пустая строка, в которой нет ни одного символа Строковые константы можно соединять знаком +: "Python" + " - " + "это наш выбор!" Значением этого выражения будет строка Python - это наш выбор! (Рис. 1). Рис. 1 Кавычки не входят в строку, а только отмечают её границы! "205" "14.007" "2 + 2" - тоже строковые константы! Они имеют строковый тип, а не числовой, поэтому значение выражения "2 + 2" вовсе не равно 4! Кроме того, существуют логические константы/литералы: True (соответствует значению истина) и False (ложь). Такие явные константы и константные выражения можно использовать в любых операторах и для этого их не нужно объявлять. 87
Обобщение Литералы – это неизменяемые (константные, фиксированные, постоянные) значения, которые могут быть: • Строковыми (символы в одинарных или двойных кавычках: "Строковый литерал", 'Строковый литерал') • Целочисленными (число без десятичной точки: 2022) • Вещественными (число с десятичной точкой: 2.022) • Логическими (True и False) Переменные перед их использованием должны быть определены. Переменные получают своё начальное значение при инициализации в операторе присваивания. Затем они могут изменять его сколько угодно раз в операторе присваивания. Переменные имеют тип, который они получают в операторе присваивания. Переменные могут изменять свой тип, когда получают новое значение. Переменные имеют идентификатор, по которому к ним можно обращаться в исходном коде. Идентификаторы переменных записывают строчными буквами. В Питоне отсутствуют именованные константы. Вместо них используют переменные. Чтобы отличать константы от переменных, идентификаторы констант принято записывать ПРОПИСНЫМИ буквами. В программе вместо идентификаторов констант и переменных используются их значения. Для констант – то значение, которое они получили при определении, для переменных – их текущее значение. 88
Занятие_6. Визуальное программирование Вероятно, многие из вас знакомы с визуальным языком программирования Скретч (Scratch). Вся программа в визуальных языках состоит из цветных блоков (Рис. 1). Рис. 1 Главный герой программ на Скретче – это котёнок по имени Скретч (Рис. 2). Слово scratch в переводе с английского значит царапина или царапать, что вполне подходит к любому котёнку. 89
Рис. 2 Визуальные программы с блоками выглядят очень красиво и привлекательно, но годятся только для начинающих программистов. Большие визуальные программы занимают очень много места на экране, поэтому в них очень сложно ориентироваться. Нас, конечно, интересует не детский язык программирования Скретч, а взрослый Питон. На это случай в Интернете имеется программа EduBlocks. Откройте официальную страницу этой программы по адресу: https://edublocks.org/ На Рис. 3 хорошо видны цветные блоки, как и в программах на Скретче. Оригинальный текст написан по-английски, но браузеры легко справляются с переводом на русский язык. Нажмите кнопку Начало работы (Рис. 4). 90
Рис. 3 Рис. 4 Если вы хотите работать в этой программе и сохранять свои проекты, то нажмите кнопку Вход (Рис. 5). Рис. 5 Регистрация на сайте очень простая – введите адрес своей электронной почты и нажмите кнопку Регистрация (Рис. 6). 91
Рис. 6 В начале следующей сессии вам, возможно, придётся сделать то же самое, но тогда нажмите кнопку Вход. После регистрации нажмите кнопку Новое (Рис. 7). Рис. 7 Программы в EduBlocks можно писать на нескольких языках, поэтому щёлкните по табличке с надписью Python 3. В правом верхнем углу появится синий кружок (Рис. 8). 92
Рис. 8 Введите с клавиатуры имя файла и нажмите кнопку Начать кодирование (Рис. 9). Рис. 9 Откроется среда разработки программ на Питоне (Рис. 10). Рис. 10 Вся страница поделена на несколько частей (Рис. 11). Сверху располагаются элементы управления. Слева – закладки/вкладки с блоками. Основ- 93
ную часть окна занимает область редактирования программы. Здесь мы будем собирать программу из блоков. Справа от области редактирования находится исходный текст, или код на языке Питон. Здесь вам ничего изменять не нужно. А вот поглядывать, как выглядит программа в текстовом формате, – это обязательно и непременно. Рис. 11 Один блок в области редактирования уже на месте – это комментарий, указывающий начало программы (Рис. 12). Рис. 12 Справа вы можете набирать программу с клавиатуры в текстовом режиме, но пока вам это лучше не делать. Более того, если вы переставите или добавите блоки в области редактирования, исходный текст сразу изменится. В первой строчке исходного кода вы видите тот же самый комментарий (Рис. 13). Рис. 13 94
Про комментарии вы уже всё знаете. В правом верхнем углу области элементов управления найдите кнопку Запустить (Рис. 14) и нажмите её. Рис. 14 Интерпретатор Питона пропускает все комментарии, поэтому никаких изменений на экране вы не увидите, но вместо кнопки Запустить появится кнопка Остановка (Рис. 15). Нажмите её, чтобы завершить программу. Рис. 15 Кнопки Запустить = и Остановка = главные. Первая запускает программу, а вторая завершает её. - самые Если вы хотите и дальше пользоваться своими проектами, то после важных изменений в программе нажимайте кнопку Сохранить (Рис. 16). После сохранения программы вы увидите надпись Saved!, а также появится новая круглая кнопка Share Projects (Рис. 17). Если вы нажмёте эту кнопку, то откроется список дальнейших действий (Рис. 18). 95
Рис. 16 Рис. 17 Рис. 18 96
Нажмите кнопку Copy Link, чтобы получить ссылку на своей проект на сайте EduBlocks. Вы увидите окно Copied! с полоской, уменьшающейся влево (Рис. 19). Рис. 19 Когда окно исчезнет, в буфере обмена будет лежать ссылка на ваш проект: https://project.edublocks.org/gFba Сохраните её, если вы планируете делиться своими проектами с друзьямитоварищами. В левом верхнем углу страницы найдите название программы и кнопку Export Project с облачком и стрелкой (Рис. 20). Рис. 20 Нажмите эту кнопку и щёлкните мышкой по строчке Export Blocks, если вы хотите сохранить свою программу в блочном варианте на своём компьютере. Строчка Export Code сохранит программу в текстовом виде (Рис. 21). Рис. 21 В папке Загрузки/Downloads появятся 2 новых файла (Рис. 22). Рис. 22 Программы на Питоне имеют расширение .py, а блочные - .xml. 97
Щёлкните по строчке в верхней части страницы, чтобы перейти на Главную страницу сайта. Здесь вы найдёте большие кнопки с вашими последними проектами (Рис. 23). Щёлкните по кнопке, чтобы открыть проект для редактирования. Рис. 23 В левой части страницы очень много разных кнопок. Нажмите кнопку Projects (Рис. 24), чтобы открыть страницу со своими проектами (Рис. 25). Рис. 24 Здесь вы можете открыть свой проект (Open) или удалить его (Delete). На этой странице удобно начинать новые проекты (Рис. 26). 98
Рис. 25 Рис. 26 Кнопка Import (Рис. 27) открывает диалоговое окно, в котором вы можете выбрать свои ранее сохранённые на диски программы и загрузить для редактирования. Рис. 27 В верхней части страницы, под названием программы находятся 3 кнопки-переключателя (Рис. 28). Рис. 28 99
Активная кнопка выделена синим цветом и подчёркиванием. По умолчанию действует режим Split, когда вы одновременно видите область редактирования с блоками и исходный код. Кнопка Blocks убирает исходный код, и вы получаете больше места для блочного редактирования. Кнопка Code оставляет на экране только исходный код. Я советую вам не переключаться с режима Split, чтобы одновременно с блочным редактированием изучать и настоящий язык программирования. На этом знакомство со средой разработки программ можно считать законченным, и мы можем заняться программированием. Помните, как в нашей первой программе мы передавали строку-привет Питону? Если вы сделаете то же самое в EduBlocks и запустите программу (Рис. 29), то на экране наше дружеское приветствие не появится. Рис. 29 Дело в том, что в настоящих программах строка "Привет, Питон" – это строковый литерал, а не исполняемая команда, поэтому она сама по себе ничего не делает. А вот чтобы напечатать строку, её следует передать в функцию print (Рис. 30, слева), которая покажет строку на экране (Рис. 30, справа). Рис. 30 Рекламная строка Powered by trinked не имеет отношения к нашей программе. Теперь давайте соберём эту программу из блоков. Как вы помните, вдоль левой границы страницы располагаются закладки (вкладки). Если щёлкнуть по закладке, то откроется группа блоков, которые имеют одинаковое назначение. Щёлкните по вкладке Statements (Операторы) и нажмите левую кнопку мышки на блоке print('Hello World') (Рис. 31). 100
Рис. 31 Перетащите блок в область визуального редактирования программы и приблизьте этот блок к блоку с комментарием. На Рис. 32 вы видите, что у выступа блока с комментарием появился жирный жёлтый контур, который сигнализирует, он готов принять новый блок. Рис. 32 Когда впадина нового блока войдёт в выступ блока с комментарием, вы услышите щелчок, и новый блок пристыкуется к блоку с комментарием (Рис. 33). 101
Рис. 33 Одновременно обновится и текстовый вариант программы (Рис. 34). Рис. 34 Строка Hello World в блоке print находится в белом прямоугольном окошечке с закруглёнными углами. В это окошечко можно записать любой текст. Выделите мышкой строку в окошечке (Рис. 35). Рис. 35 И введите с клавиатуры наш дружеский привет (Рис. 36). Рис. 36 102
Обратите внимание, что кавычки уже стоят на месте, поэтому строку не нужно дополнительно обрамлять кавычками! Исходный текст тоже изменился (Рис. 37). Рис. 37 Запускаем программу, и Питон получил наш привет, как и раньше (Рис. 38). Рис. 38 Согласитесь, визуальное программирование – это очень интересно, но… Кроме перетаскивания цветных блоков мышкой, всё равно придётся работать ручками и на клавиатуре. Давайте изучим некоторые возможности области редактирования. Вызовите контекстное меню на блоке print и щёлкните по строчке Duplicate (Сделать копию) (Рис. 39). Рис. 39 103
В области редактирования появится копия блока print. На Рис. 40 хорошо видно, что новый блок неактивный. Исправляем сообщение (Рис. 41). Рис. 41 И пристыковываем новый блок к программе (Рис. 42). Рис. 42 104
Текстовый код синхронно изменился (Рис. 43). Рис. 43 Запускаем программу и отсылаем 2 привета (Рис. 44). Рис. 44 Если вы хотите изменить порядок блоков, то подхватите мышкой нижний блок и пристыкуйте его к блоку с комментарием (Рис. 45). Рис. 45 Обратите внимание, что блок соответствует одной строке в исходном коде. Чтобы временно убрать блок, оттащите его мышкой на свободное место области редактирования (Рис. 46). Если блок вам больше не нужен, уничтожьте его (Рис. 47). Любой блок можно просто деактивировать (Рис. 48). А затем снова активировать (Рис. 49). 105
Рис. 46 Рис. 47 Рис. 48 106
Рис. 49 Чтобы передвигать область редактирования, пользуйтесь полосками прокрутки снизу и справа. Или нажмите левую кнопку мышки на свободном месте области редактирования и двигайте мышку в любую сторону (Рис. 50). Рис. 50 Найдите в правом нижнем углу области редактирования 3 кнопки (Рис. 51). Рис. 51 107
• Кнопка с плюсом увеличивает размеры блоков. • Кнопка с минусом уменьшает размеры блоков. • Кнопка со знаком равно возвращает размеры блоков в исходное состояние и перемещает все блоки в середину области редактирования. Масштабировать блоки можно и с помощью колёсика мышки. Для тренировки попередавайте приветы всем, кому пожелаете. 108
Занятие_7. Визуальная арифметика Сохраните первый проект и вернитесь на предыдущую страницу. Там вы увидите свой проект (Рис. 1). Чтобы открыть его, дважды щёлкните мышкой по картинке. Рис. 1 Но сейчас этого делать не нужно. Нажмите кнопку New, дайте приличное имя новому проекту и нажмите кнопку Start Coding (Рис. 2). Рис. 2 Мы уже узнали у Питона, что 2 плюс 2 равно 4. Давайте убедимся в этом визуально. Среда разработки требует, чтобы результат арифметической операции был присвоен переменной, иначе мы не сможем его напечатать. Нам это хорошо и на руку: и арифметику вспомним, и научимся переменные использовать в программах. Чтобы создать переменную, откройте вкладку Variables (Переменные) (Рис. 3). 109
Рис. 3 Нажмите кнопку Create variable… (Создать переменную…) (Рис. 4). Рис. 4 Многоточие в конце предложения говорит о том, что будет открыто диалоговое окно. В диалоговом окне, в текстовое поле New variable name: (Имя новой переменной) введите с клавиатуры имя переменной и нажмите кнопку Продолжить (Рис. 5). Рис. 5 Имя переменным вы давать умеете. Чтобы был понятен смысл переменной, её можно назвать также по-английски result или res. Откройте вкладку Math (Рис. 6), где уже ждёт нас вся питонья математика. Рис. 6 Перетащите самый верхний блок (Рис. 7) в область редактирования. 110
Рис. 7 Вместо литералов True наберите с клавиатуры слагаемые (Рис. 8). Если вы нажмёте мышкой на белый треугольник, то раскроется список всех арифметических операторов, которые вам уже известны (Рис. 9). Рис. 8 Рис. 9 Вы можете выбрать из этого списка любой оператор, но сейчас этого делать не нужно, поскольку знак плюс стоит по умолчанию. Перетащите блок с переменной otvet в область редактирования и пристыкуйте его к верхнему блоку. По умолчанию числовые переменные получают нулевое значение (Рис. 10). Рис. 10 В окошечко с нулём перетащите арифметический блок (Рис. 11). 111
Рис. 11 Так мы присваиваем переменной otvet сумму двух слагаемых (Рис. 12). Рис. 12 Поскольку мы хотим узнать значение переменной, то нам нужно напечатать его на экране. Обычный блок print для этого не годится, потому что он напечатает строку "2 + 2", а вовсе не сумму двух слагаемых. Раскройте вкладку Statements и перетащите блок print( Variable ) (Рис. 13) в область редактирования. Рис. 13 Нетрудно догадаться, что в окошечко Variable нужно записать имя переменной otvet (Рис. 14). Рис. 14 Пристыкуйте блок print к программе – и она полностью готова к работе (Рис. 15). Запускаем программу и получаем правильный ответ (Рис. 16). 112
Рис. 15 Рис. 16 Вы можете не печатать имя переменной, а вставить в окошечко блок с именем переменной из вкладки Variables (Рис. 17). Результат вы получите тот же самый. Рис. 17 Мы получили верный ответ, но он не очень понятен. Лучше было бы напечатать полный ответ, как показано на второй строке Рис. 18. Рис. 18 Для этого нам нужен блок print(Variable) (Рис. 19). 113
Рис. 19 Вместо имени переменной мы можем передать ему строку для печати. В этой строке мы сами расставим кавычки, потому что блок print(" ") (Рис. 20) всю строку целиком заключает в кавычки. Рис. 20 Для сборки сообщения нам нужен блок для конкатенации двух строк (Рис. 21). Рис. 21 В первое окошечко записываем строку с условием (Рис. 22). Рис. 22 Во второе окошечко нужно поместить ответ, то есть переменную otvet. Но переменная имеет числовой тип, а нам нужна строка. Вы уже знаете, что для преобразования чисел в строку служит функция str, которой соответствует одноимённый блок (Рис. 23). Рис. 23 Переносим блок с переменной otvet прямо в окошечко блока str (Рис. 24). Строка для печати готова (Рис. 25). 114
Рис. 24 Рис. 25 Вставляем блок со строкой в окошечко блока print(Variable) (Рис. 26). Рис. 26 И пристыковываем его к программе (Рис. 27). Рис. 27 Запускаем программу и получаем ответ, который вы уже видели раньше (Рис. 28). Рис. 28 115
Две строки для печати на экране можно не соединять знаком плюс, а разделить их запятой (Рис. 29). Рис. 29 В этом случае пробел между строками вставляется автоматически, поэтому в конце первой строки он не нужен (Рис. 30). Рис. 30 Сохраните проект и начните новый (Рис. 31). Рис. 31 Калькулятор Наш калькулятор очень простой, но он умеет складывать любые числа! В первую очередь, мы должны позаботиться о вводе чисел в программу. Для этого служат функция и блок input (Рис. 1). Рис. 1 116
Перетащите блок input в область редактирования и измените подсказку (Рис. 2). Рис. 2 Даже если мы введём с клавиатуры число, то блок input всё равно вернёт строку. Чтобы преобразовать строку в число, мы должны передать строку в блок int (Рис. 3). Рис. 3 Полученное число нам пригодится дальше, поэтому его нужно сохранить в переменной. Создайте переменную number_1 (Рис. 4). Рис. 4 Присвойте переменной введённое число (Рис. 5). Рис. 5 Пристыкуйте готовый блок к программе (Рис. 6). Рис. 6 117
Для контроля печатаем значение переменной number_1 на экране (Рис. 7). Рис. 7 Запускаем программу, получаем приглашение ввести число и делаем это (Рис. 8). Рис. 8 Программа работает верно. Повторяем все действия для ввода второго числа (Рис. 9). 118
Рис. 9 Проверяем программу в работе. Она нас не подвела (Рис. 10). Рис. 10 Собираем из блоков сумму двух переменных (Рис. 11). Рис. 11 И печатаем её на экране (Рис. 12). Рис. 12 119
Считать наша программа умеет (Рис. 13). Рис. 13 Наша задача – научить её красиво печатать ответ (Рис. 14). Рис. 14 Создаём переменную otvet и присваиваем ей сумму двух ведённых чисел (Рис. 15). Рис. 15 Чтобы из чисел получить строку, преобразуем их в строки с помощью блока str. Теперь нам предстоит из нескольких вложенных блоков для конкатенации строк (Рис. 16) собрать длинную строку (Рис. 17). Рис. 16 Рис. 17 Деактивируем ненужные блоки – и калькулятор готов к бою (Рис. 18). 120
Рис. 18 Наш калькулятор отлично показал себя в боевых условиях (Рис. 19). Рис. 19 К сожалению, калькулятор у нас получился однозарядный: после вычисления первой суммы программа завершает работу. Чтобы проводить вычисления многократно, нам нужен бесконечный цикл while. О циклах мы поговорим позже, но действие цикла while легко понять и без подробных объяснений: он выполняет все блоки внутри себя. Откройте закладку Loops (Циклы) и перетащите блок while в область редактирования (Рис. 20). Рис. 20 121
Отстыкуйте все блоки нашей программы и пристыкуйте блок while (Рис. 21). Рис. 21 Вставьте все блоки внутрь блока while (Рис. 22). Рис. 2 Теперь все блоки внутри блока while будут выполняться «бесконечно» (Рис. 3). 122
Рис. 3 Запустите программу. Калькулятор будет исправно работать, пока вы не нажмёте кнопку Stop (Рис. 4). Рис. 4 Для тренировки соберите из блоков калькуляторы и для других арифметических действий. Сохраните программу и создайте новый проект Кошки-мышки (Рис. 5). Рис. 5 123
Кошки-мышки Давайте решим настоящую задачу, которую мы уже решали на третьем занятии. Создайте переменную otvet и присвойте ей значения двумя разными способами, которые вы изучили. Напечатайте ответ на экране. Должно получиться не только правильно, но и красиво (Рис. 1). Рис. 1 Всегда сравнивайте блочную программу с текстовой (Рис. 2)! В будущем вы будете писать именно так, а не складывать блоки стопкой. Рис. 2 Шахматная задача И знаменитую шахматную задачу также решаем двумя способами (Рис. 1). 124
Рис. 1 Единственное отличие этого решения от решения в IDLE состоит в том, что для печати результата вычислений мы вызываем функцию print. Запомните: в программах вы никак иначе не напечатаете ни строки, ни числа. Число шахматных партий Обычно программисты разбивают длинные выражения на части. Для этого вы можете объявить несколько переменных. Но если вы не боитесь запутаться в арифметическом выражении, то можете сразу напечатать результат вычислений (Рис. 1). Рис. 1 125
Вы уже знаете, как вычислить длину строки (число символов в ней, не пикселей и не сантиметров), поэтому добавьте ещё 1 составной блок к нашей программе (Рис. 2). Рис. 2 Длина строки нам известна – 117 символов. На вкладке Statements имеется замечательный блок с пустым окошечком и комментарием (Рис. 3). Рис. 3 Перетащите его в область редактирования (Рис. 4). Рис. 4 126
Код вы можете ввести с клавиатуры или скопировать из исходника (Рис. 5). Рис. 5 Вставьте текст в окошечко и пристыкуйте блок к программе (Рис. 6). Рис. 6 Запускаем программу – и полноблочный, и одноблочный вариант действуют одинаково (Рис. 7). Рис. 7 127
Из этого следует, что вы можете успешно заменять сложные вложенные блочные конструкции обычным текстом на языке Питон. Так вы быстрее научитесь писать настоящие программы! Какая разница? Эта задача должна стать для вас лёгкой прогулкой с Питоном (Рис. 1). Рис. 1 Складывание бумаги Создаём 3 переменные с теми же именами, что и в формуле. Присваиваем им нужные значения, которые печатаем на экране (Рис. 1). Чтобы сократить код, просто печатаем результат вычислений, без присваивания его переменной d (Рис. 2). Продолжайте делать копии блоков и пристыковывать их к программе, пока не доберётесь до n = 20. Запускаем программу и наглядно видим, как стремительно растёт высота бумаги (Рис. 3). 128
Рис. 1 Рис. 2 Рис. 3 Вы, конечно, заметили, что мы многократно повторяем одни и те же операции. Обычно их проводят в циклах, которые вы скоро изучите. 129
Три цифры - раз Очень простая задача (Рис. 1)! Рис. 1 Запускаем программу и получаем великолепный ответ (Рис. 2). Рис. 2 Три цифры - два Программа для решения этой задачи тоже очень простая (Рис. 1). Рис. 1 130
Главное – правильно записать арифметические выражения в функции print. А результат - налицо (Рис. 2). Рис. 2 Гугол Гугол – это огромное число, но его вычисление – очень простая задача, которая решается в одну строчку (Рис. 1). Рис. 1 Задача Рачинского Визуальное решение арифметических задач – это красиво и весело (Рис. 1). Проверяем остальные арифметические выражения. И здесь всё верно (Рис. 2). 131
Рис. 1 Рис. 2 Вычисление сложных арифметических выражений В этой задаче главное – правильно расставить звёздочки (Рис. 1). Рис. 1 132
Занятие_8. Операции и операторы Операции - это действия, которые применяются к объектам программы (операндам) – к переменным, константам и функциям. Вы уже знаете, например, такие операции: определение переменных, присваивание переменным значений, вызов функций. Дальше вы познакомитесь и с другими, более сложными операциями. Знаки операций (операторы) предназначены для обозначения этих действий. Это могут быть особые символы: + - * / < > =, а также зарезервированные слова: int, str, float и другие. При использовании зарезервированного слова в качестве знака операции он должен быть отделён от операндов хотя бы одним пробелом! Для односимвольных операторов соблюдение этого требования необязательно, поэтому вы можете записывать операцию сложения поразному: x=max+x+1 x = max+x+1 x = max + x + 1 Результат выполнения операций одинаков, но последняя форма более понятна при чтении и разборе исходного кода. Часто операторами называют инструкции, то есть команды, которые выполняет интерпретатор языка программирования. Это приводит к путанице. Рассмотрим пример: x = max + x + 1 Здесь символы = и + - это операторы. Естественно, эти символы выполнить нельзя. Из операторов и операндов можно составить выражение, которое имеет тип и значение. В нашем примере max + x + 1 – это выражение числового типа. Значение и тип выражения зависит от текущих значений переменных max и x. Знак равенства – это оператор присваивания. Вся строка x = max + x + 1 в целом – это инструкция. Интерпретатор выполняет её так. Сначала вычисляется значение правой части инструкции, а затем полученное значение присваивается переменной в левой части инструкции. 133
Чаще всего инструкция занимает одну строку в исходном тексте, но в некоторых случаях (о них речь впереди) необходимо составить из однострочных инструкций блок, который обрабатывается так же, как и однострочная инструкция. В этом случае инструкции записываются с отступом. Внутри одного блока инструкций могут быть и другие блоки, которые называются вложенными. Операции делятся на унарные (одноместные) и бинарные (двуместные). В унарных операциях участвует знак операции и следующий за ним операнд: variant = 1 variant = -variant variant = +variant В бинарных операциях участвуют 2 операнда, и знак операции записывается между ними: variant = variant + 5 variant = 2 * 3 coef = 3 variant = 5 / coef Для каждого типа данных существует свой набор операций, поэтому операнды должны быть одного типа или совместимых типов. Выражения Самое простое выражение состоит из одного операнда. Это может быть переменная, константа, литерал. Мы уже много раз пользовались такими простейшими выражениями: 123 peremennaya "Литерал" Выражение – это не инструкция, а составная часть инструкции, которая имеет тип и значение. Большинство простых выражений используются в инструкциях присваивания, в логических операторах и в операторах циклов, с которыми вы вскоре познакомитесь. 134
Конечно, гораздо чаще встречаются «полновесные» выражения, состоящие из нескольких операндов и знаков операций: 1 + 2 2 * 2 3 * 4 + 5 – 6/2 -12 -2.67 * PI + -3/2 - 7.01 Между числами и знаками операций может быть любое число пробелов, но можно печатать их и вплотную друг к другу. О вреде последнего способа записи выражений мы уже говорили. Выражения могут состоять не только из числовых (и всех других) констант, но и из идентификаторов переменных, вызовов функций и круглых скобок. Большинство выражений имеют какое-либо значение, которое получается после его вычисления. Если выражение представляет собой вызов функции, которая не возвращает значения, например print, то оно не имеет значения. Например, вызов функции input возвращает значение типа str. Это значение, как вы знаете, равно строке, которую пользователь ввёл с клавиатуры. Возвращаемое значение можно использовать в выражении, а можно и проигнорировать. Выражение с вызовом input '25 ' + input() имеет тип str, поскольку и возвращаемое значение, и строковый литерал имеют этот тип. Если тип переменной отличается от типа выражения, то переменная получит новый тип. Нередко операнды в сложном выражении имеют разные типы. В этом случае к ним применяются правила преобразования типов. Важно понять, что при вычислении выражений вместо имён переменных и констант подставляются их текущие значения, а вместо вызова функции – возвращаемое значение. Например, при вычислении выражения 135
-2.67 * PI + -3/2 - 7.01 вместо константы PI будет подставлено её значение 3.14159265358979: -2.67 * 3.14159265358979 + -3/2 - 7.01 Результат выражения – число -16.3980523850847 типа float. При вычислении значения выражения '25' + input() Вместо вызова функции input будет подставлено возвращаемое значение. Например, если пользователь ввёл строку ' тысяч' и нажал клавишу ПРОБЕЛ, то эту строку : '25' + ' тысяч' Результат выражения – строка '25 тысяч' типа str. Если текущее значение переменной i равняется 12 i = 12 то при вычислении выражения i + 21 вместо идентификатора i будет подставлено число 12, то есть значением выражение будет целое число 33 типа int. Операции преобразования типов Операции преобразования типов мы уже подробно разобрали на предыдущих занятиях, поэтому не будем повторяться, а только коротко обобщим изученный материал. 1. Все переменные и константы получают тип и значение при их определении. 2. Переменным можно присваивать новые значения любого типа. 3. Если тип данных отличается от типа переменной, то переменная получает новый тип. 136
4. Если преобразование числового типа не приводит к потере данных, то оно проводится автоматически. Такое преобразование типов называется неявным (implicit). Например, тип int автоматически приводится к типу float. 5. Если числовые типы совместимы, но возможна потеря данных, то необходимы явные преобразования (explicit), или приведения. Такие операции выполняются оператором приведения: PI = 3.14 iPi = int(PI) В данном примере необходимо приведение типов, поскольку целый тип int не может хранить вещественные числа. Оператор (функция) int приводит тип константы float к типу int. При этом дробная часть вещественного числа отбрасывается. Вы также знакомы с функцией str, которая преобразует числа в строки. Инструкция определения При определении новой переменной её инициализируют (присваивают начальное значения, которое затем может быть изменено). При определении константы ей необходимо присвоить значение, которое не изменяется по ходу программы. С такими инструкциями вы встречались многократно: j = 12 # инструкция определения переменной NUM = 123 # инструкция определения константы Обобщим наши знания в «шпаргалке»: имя_переменной = выражение ИМЯ_КОНСТАНТЫ = выражение Выражение: • для переменной – другая переменная, константа, константное выражение, функция, а также сложное выражение из переменных и констант, соединённых знаками арифметических операций; 137
• для константы – то же самое. Рассмотрим, как действует оператор определения новой переменной. Компилятор выделяет для переменной область памяти для хранения её значения. Поскольку переменная при инициализации получает значение определённого типа, то компилятор точно знает, сколько байтов памяти необходимо зарезервировать. Например, для переменной типа int необходимо 4 байта, а для переменной типа float – 8. В некоторых языках программирования, например в Си-шарпе, можно объявлять переменные: Point start, finish; string s; При этом глобальные переменные автоматически получают значение по умолчанию для заданного типа, а локальные переменные вообще не имеют значения, поэтому должны быть позднее инициализированы. В языке Питон объявить переменную не удастся – все переменные должны быть сразу инициализированы, то есть определены. Инструкция присваивания Самая «востребованная» инструкция – это, безусловно, инструкция присваивания. Она записывается так: имя_переменной = выражение В результате выполнения этой инструкции значение переменной станет равным значению выражения. Выражением может быть другая переменная, константа, константное выражение или вызов функции. Тип выражения определяет тип переменной. Знак операции присваивания (оператор) – это обычный знак равенства =. 138
В языке программирования паскаль оператор присваивания записывается иначе - :=. Так, конечно, более понятно назначение этого оператора. Однако в большинстве языков программирования оператор присваивания обозначается знаком равенства. Например: Результат присваивания, значение переменной Оператор присваивания width = 100 100 height = width + 20 120 snum = "Двенадцать" Двенадцать snum = "Двенадцать" + str(1) Двенадцать1 s = snum + str(height) Двенадцать1120 Действие инструкции присваивания заключается в том, что в зарезервированные ячейки памяти записывается указанное значение переменной (константы или выражения). Все данные, которые там хранились раньше, стираются. При инициализации инструкция присваивания определяет новую переменную, а затем только изменяет значение уже существующей переменной. Проект Периметр правильного треугольника У правильного треугольника 3 одинаковых стороны, что хорошо видно на Рис. 1. Рис. 1 139
Пусть длина стороны треугольника равна а. Нужно найти периметр треугольника. Задача элементарная, но она поможет вам развить навыки программирования! Чтобы находить периметры разных треугольников, заключим все вычисления в бесконечный цикл while (Рис. 2). Рис. 2 Создайте переменную а (Рис. 3). Рис. 3 Значение переменной а – это и есть длина стороны треугольника. Мы хотим получить её от пользователя программы, значит, нам нужен блок input. Он вернёт строку, которую ввёл пользователь. Обычно блок input содержит подсказку (Рис. 4), иначе пользователь будет озадачен, и мы его потеряем. Рис. 4 Длина стороны измеряется числами, а не буквами, поэтому нам нужно преобразовать строку в число. Тут важно определиться, какие могут быть 140
длины сторон. Скорее всего, не всегда целые, поэтому преобразуем строку в вещественное число с помощью блока float (Рис. 5). Рис. 5 Вот теперь мы можем присвоить переменной а заданное пользователем значение, то есть длину стороны треугольника (Рис. 6). Рис. 6 Создайте переменную p, в которую мы запишем периметр треугольника (Рис. 7). Рис. 7 Чтобы найти периметр треугольника, нужно умножить длину стороны а на 3: p = a * 3 Для вычислений используем первый блок на вкладке Math (Рис. 8). 141
Периметр мы вычислили (Рис. 9). Рис. 9 Присваиваем вычисленное значение переменной р (Рис. 10). Рис. 10 Периметр найден, но нам нужно ещё напечатать его на экране, иначе пользователь так ничего и не узнает. Для этого годится блок print (Рис. 11). Рис. 11 Мы могли бы просто напечатать число, но оно вряд ли будет понятно, поэтому печатаем сообщение в кавычках, а затем через запятую имя переменной р (Рис. 12). Чтобы отделить вычисления друг от друга, вставляем в конец цикла while блок print без аргументов – он просто переведёт строку (Рис. 13). 142
Рис. 12 Рис. 13 Запускаем программу, вводим длину стороны правильного треугольника, а всё остальное делает программа (Рис. 14). 143
Рис. 14 Проект Периметр квадрата https://project.edublocks.org/3MEY Квадрат, или правильный четырёхугольник в смысле периметра отличается от правильного треугольника только числом сторон. Если кто-то забыл, сколько сторон у квадрата, то Рис. 1 быстро напомнит. Рис. 1 Закрепляем изученный материал (Рис. 2). Закрепление прошло успешно (Рис. 3). 144
Рис. 2 Рис. 3 Проект Длина окружности https://project.edublocks.org/RRF1 Точно так же вы можете вычислить периметр любого правильного многоугольника, просто изменяя число сторон. Вы даже можете сделать программу более универсальной, если позволите пользователю вводить и число сторон многоугольника. Если мы будем увеличивать число сторон правильного многоугольника, то получим окружность. Длина окружности c = 2𝞹r или c = 𝞹d 145
Мы вычислим длину окружности по первой формуле (Рис. 1), а затем вы самостоятельно соберёте из блоков программу для вычисления длины окружности по второй формуле. Рис. 1 Соберите из блоков программу для вычисления периметра произвольного прямоугольника. Соберите из блоков 4 программы для вычисления площади правильного треугольника, квадрата, круга и прямоугольника. Соберите из блоков 2 программы для вычисления площади боковой поверхности и объёма куба, а также прямоугольного параллелепипеда. Проект Прямоугольный треугольник Типичная задача из школьной геометрии: по двум известным катетам a и b найти гипотенузу c, периметр и площадь прямоугольного треугольника. 146
Самое сложное в этом проекте – вспомнить (или найти) формулу для вычисления длины гипотенузы (Рис. 1). Рис. 1 Треугольные дела (Рис. 2). Рис. 2 Проект Обмен значениями https://project.edublocks.org/PDgh Давайте отдохнём от геометрии, решая задачи по программированию (это лучший отдых!). 147
Обмен значениями – типовая задача в программировании: нужно поменять значения двух переменных a и b. Хитрость этой операции заключается в том, что в результате выполнения очевидного кода: a = b b = a обмена значениями не произойдёт! После выполнения первой инструкции присваивания переменная а получит значение переменной b. Поэтому вторая инструкция не изменит значение переменной b, поскольку переменная а уже получила то же самое значение b. Таким образом, вместо обмена значениями обе переменные будут иметь одинаковое значение b. В таких случаях используется вспомогательная переменная tmp, в которой необходимо сохранить значение одной из переменных. В нашем примере – переменной а. Тогда вторая инструкция присваивания должна быть такой: b = tmp А собрать из блоков программу – это для нас лёгкая работа (Рис. 1). Рис. 1 148
Проверка подтверждает – обмен произошёл успешно (Рис. 2). Рис. 2 Именно так обмениваются значениями переменные во многих языках программирования, но в Питоне можно обойтись без вспомогательной переменной! Тогда вся задача решается одним блоком (Рис. 3). Рис. 3 Питон – на высоте (Рис. 4). 149
Рис. 4 Проект Фаренгейт https://project.edublocks.org/Rwh4 Очень часто нужно перевести одни единицы измерения в другие. Обычно формулы перевода очень простые, поэтому мы разберём только несколько примеров. Например, в России температуру измеряют в градусах Цельсия (обозначаются буквой С), а в США – в градусах Фаренгейта (обозначаются буквой F). Формулы для перевода одних градусов в другие несложные, но в уме всё равно считать трудно. Поскольку градусы выражаются дробными числами, то мы используем переменные типа float. В этом проекте мы переведём градусы Фаренгейта в градусы Цельсия. Как сейчас принято говорить, в культовом романе Рэя Брэдбери 451 градус по Фаренгейту (Рис. 1), рассказывается о печальном будущем человечества, когда все книги, заставляющие думать, будут сжигаться. 451 градус по Фаренгейту – это как раз температура воспламенения бумаги. Что касается будущего, то оно уже наступило (роман был впервые издан в 1953 году, так что ждать пришлось недолго). Правда, для этого книги сжигать не пришлось – тут классик жанра ошибся… 150
Рис. 1. Обложки книг Рэя Брэдбери Перевести формулу для пересчёта градусов Фаренгейта в градусы Цельсия нам не составит труда (Рис. 2): F-32 C = ----1.8 Рис. 2 151
Проект Цельсий https://project.edublocks.org/Ksa1 Здесь мы делаем то же самое, но наоборот (Рис. 1): F = 1.8C + 32 Рис. 1 Наш перевод с фаренгейта на цельсий (Рис. 2). Рис. 2 152
Обобщение Выражения – это строки, состоящие из операндов (аргументов, данных), операторов (знаков операций) и круглых скобок. Каждое выражение имеет тип (строковый, символьный, числовой, логический) и значение этого типа, которое компилятор вычисляет, применяя к операндам указанные операции (действия). Порядок выполнения операций зависит от их приоритета (например, умножение и деление выполняются раньше сложения). Порядок выполнений действий можно изменить с помощью круглых скобок. При вычислении выражений, в которые входят операнды разных типов, они предварительно приводятся к одному типу. Операнды типа int преобразуются к типу float автоматически, в других случаях от программиста может потребоваться явное преобразование типов (приведение). Задания для самостоятельного решения Get Ready! for Standardized Tests Math Grade 3 Решите несколько примеров из книги [Osborne02]: 322 + 409 + 786 + 250 16 + 27 + 87 +34 456 + 985 3626 + 7597 4.36 + 8.98 Задача #837 Математическая шкатулка Вычислите сумму наибольших однозначного, двузначного, трёхзначного и четырёхзначного чисел. Ответ: 9 + 99 + 999 + 9999 153
Задача #3.1 Удивительный мир чисел, стр. 42 Число 32 Десятичная запись куба этого числа начинается самим числом, а запись его пятой степени оканчивается цифрами данного числа: 323 = 32768 325 = 33554432. Проверьте эти равенства. Степени записывайте как произведения: 323 → 32 * 32 * 32 Задача #10 Математическая шкатулка Найдите возможно быстрее, какое частное и какой остаток получатся при делении числа 1 ⦁ 2 ⦁3 ⦁ 4 ⦁ 5 ⦁ 6 + 1 на 5. Ответ: Частное равно 2 ⦁3 ⦁ 4 ⦁ 6 = 144, остаток равен 1. Задачи #45, 46, 47, 58 Математическая шкатулка Сколько суток составляет миллион минут? Сколько лет составляет миллион часов? Сколько столетий составляет миллион дней? Прошёл ли с начала нашего летосчисления миллион дней? Сколько столетий в миллиарде минут? Задачи #70, 71, 72, 74, 75 Математическая шкатулка 154
Земля при своём движении вокруг Солнца проходит путь в 936 250 000 км в год. Какое расстояние проходит Земля за 1 сутки? (Считайте год в среднем равным 365, 25 суток.) Скорость света в вакууме ≈ 3,00 ⦁ 105 км/с. Какое расстояние проходит свет в течение года? Расстояние от Земли до звезды Проксима Центавра свет проходит за 4⅓ года. Сколько километров до этой звезды? В астрономии для выражения расстояний во вселенной используются единицы: парсек = 3,26 световых года и мегапарсек = 1 000 000 парсеков. Выразите эти единицы в километрах. Тончайшая паутиновая нить, если бы её протянуть по земному экватору, длина которого ≈ 40 060 км, имела бы массу 660 г. Какую массу имела бы такая нить, протянутая на расстояние в один мегапарсек? 155
Занятие_9. Математические операции Дважды два – четыре, дважды два четыре – Это всем известно в целом мире. Дважды два – четыре, дважды два – четыре, А не три, а не пять, это надо знать! Дважды два – четыре, дважды два – четыре, А не шесть, а не семь, это ясно всем! Детская арифметическая песенка В Питоне над числовыми константами и переменными можно производить различные арифметические действия: Знак операции Операция + Сложение - Вычитание * Умножение / % Деление Остаток от деления ** Возведение в степень Все арифметические операции относятся к бинарным, поскольку для их выполнения нужны два числа (операнда, аргумента), между которыми и ставят знак операции: Они также требуют, чтобы результат выполнения операции был присвоен переменной (или константе), которая в записи операции находится слева от оператора присваивания (результат операции может быть использован и в какой-либо другой операции). Рассмотрим примеры. Пусть: a = 6 156
b = 3 num = 0 Тогда значение переменной num после выполнения арифметических операций будет равно: Действие num = a + b Значение переменной num 9 num = a – b 3 num = a * b num = a / b; 18 2 num = a % b 0 num = a ** b 216 num = -a -6 num = +b 3 При вычислении выражений учитывается приоритет операций – точно так же, как и в математике. Сначала слева направо выполняются операции умножения, деления и деления по модулю, а затем сложения и вычитанияИзменить порядок вычислений можно с помощью круглых скобок (не квадратных и не фигурных!). В полном согласии с законами арифметики, сначала выполняются операции в скобках, затем все остальные: Действия num = (2 + 4 - 1) // 5 * 11 Значение переменной num 11 num = int(((3.1415 - 1.0) / 7.78 * (45 - 7))) 10 Точное значение: 10.4597686375 num = int(-2.67 * 3.14 + -3/2 - 7.01) -16 Точное значение: -16,8938 num = 3 * 4 + 5 – 6//2 14 Между числами и знаками операций может быть сколько угодно пробелов, но можно печатать их и вплотную друг к другу. 157
Часто скобки используют не для изменения порядка вычислений, а для повышения «читабельности» длинных выражений: m = 7 x = (m * 7.2 / 4.3) + (12 / 2.4) Проект Арифметические операции Давайте проверим данные в таблице (Рис. 1)! Рис. 1 158
Программа подтверждает, что законы арифметики выполняются и в Питоне безукоризненно (Рис. 2). Рис. 2 Если операнды имеют целый тип int и к ним не применяется операция вещественного деления, то и результат операции имеет тот же тип. Это значит, что при операции деления дробная часть будет отброшена. Если хотя бы один операнд имеет тип float или к операндам применяется операция вещественного деления, то потребуется приведение типов, что мы и выполнили в нашем проекте. Если операнды имеют вещественный тип, то результат вычислений нужно сначала округлить с помощью функции round (Рис. 3), а затем привести к целому типу int с помощью функции int. Конечно, если это необходимо. Рис. 3 Тип выражения можно определить с помощью функции type (Рис. 4). Рис. 4 159
Комбинированные операторы присваивания В программировании очень часто требуется изменить значение какойлибо переменной. Например, добавить единицу к значению переменной. Увеличение значения переменной на 1 называется инкрементом. Уменьшение значения переменной на 1 называется декрементом. n = n + 1 n = n - 1 # инкремент # декремент В Питоне имеются операторы присваивания, совмещённые с арифметическими. Например, инкремент и декремент можно иначе записать так: n += 1 n -= 1 # инкремент # декремент Аналогично можно изменить значение переменной на любую величину: n += 2 m = 3 n -= m Если сопоставить различные формы записи одной и той же операции, то легко понять, что комбинированные операторы присваивания представляют собой сокращённую запись арифметического оператора и оператора присваивания: Оператор += Операция n += 3 Эквивалент n = n + 3 -= *= n -= 2 n *= 3 n = n - 2 n = n * 3 **= n **= 3 n = n ** 3 /= %= n -= 2 n -= 5 n = n / 2 n = n % 5 Итак, операция присваивания = просто помещает вычисленное значение выражения (справа от него) в переменную (слева от него), а комбинированная: 160
1. сначала применяет соответствующий арифметический оператор 2. затем присваивает значение переменной Поскольку эти операции проводятся над данными в одном и том же месте памяти, то оба пункта 1 и 2 выполняются одновременно, то есть очень быстро. Блок присваивания значения переменной имеет только 2 комбинированных оператора (Рис. 1). Рис. 1 Вы можете использовать их в визуальной программе (Рис. 2). Рис. 2 161
Если вы хотите использовать в программе и другие комбинированные операторы присваивания, то пишите текстовую программу (Рис. 3). Рис. 3 Класс Math Для «научных» вычислений в Питоне имеется специальный класс Math, Все математические функции вы найдёте на вкладке Math (Рис. 1). Рис. 1 Там имеется два блока для констант: e – основание натуральных логарифмов и pi, значение которого равно числу π (Рис. 2). Рис. 2 Но чтобы использовать эти константы в программах, вы должны импортировать модуль math (Рис. 3). 162
Рис. 3 Зато функций в этой библиотеке вполне достаточно, чтобы выполнять довольно сложные расчёты. Для удобства пользования все функции модуля math, мы сведём в одну таблицу. е 2.71828182846 тип float pi 3.14159265359 тип float abs(num) Возвращает абсолютную величину (модуль) числа num любого числового типа. Тип значения совпадает с типом аргумента. acos(num) Возвращает угол в радианах, соответствующий значению косинуса num. Тип результата – float. asin(num) Возвращает угол в радианах, соответствующий значению синуса num. Тип результата – float. atan(num) Возвращает угол в радианах, соответствующий значению тангенса num. 163
Тип результата – float. ceil(num) Округляет заданное вещественное число num до большего целого (с избытком). Тип результата – float. сos(num) Возвращает косинус угла num, заданного в радианах. Тип результата – float. degrees(num) Конвертирует угол num, заданный в радианах, в градусы. Тип результата – float. divmod(num1, num2) Возвращает целую часть частного от деления числа num1 на число num2y и остаток от деления num1 на num2. exp(num) Возвращает экспоненту заданного числа num (e в заданной степени num). Тип результата – float. fabs(num) Возвращает абсолютную величину (модуль) числа num любого числового типа. Тип значения совпадает с типом аргумента. factorial(тгь) Возвращает факториал натурального числа num. Тип результата – int. floor(num) Округляет заданное вещественное число num до меньшего целого (с недостатком). Тип результата – float. hypot(coords) Возвращает длину гипотенузы. 164
log(num) Возвращает натуральный логарифм заданного числа num. Тип результата – double. log10(num) Возвращает десятичный логарифм заданного числа num. Тип результата – double. max(num1, num2) min(num1, num) Возвращает большее из двух чисел num1 и num2. Тип результата совпадает с типом аргумента. Возвращает меньшее из двух чисел num1 и num2. Тип результата совпадает с типом аргумента. pow(num, степень) Возвращает результат возведения числа num в заданную степень. Тип результата – float. radians(num) Конвертирует угол num, заданный в градусах, в радианы. Тип результата – float. round(num) round(num, int) Округляет заданное вещественное число num до ближайшего целого. Аргумент типа int указывает количество цифр дробной части округлённого числа. Если int = 0, то его можно не указывать. Тип результата – float. sin(num) Возвращает синус угла num, заданного в радианах. Тип результата – float. sqrt(num) Возвращает корень квадратный из числа num. 165
Тип результата – double. tan(num) Возвращает тангенс угла num, заданного в радианах. Тип результата – float. trunc(num) Возвращает целую часть заданного вещественно числа num. Тип результата – float. Модуль math имеет также функции, не представленные в таблице. Например, для вычисления гиперболических функций. Функции, отмеченные красным цветом, встроенные, они не входят в модуль math. Ими можно пользоваться без импорта этого модуля. Тут, конечно, самое время вспомнить треугольник Пифагора и его штаны (Рис. 4). Рис. 4 Самая известная пифагорова тройка чисел – 3, 4, 5, где 3 и 4 – это длины катетов, а 5 – длина гипотенузы. Проверяем теорию практикой и убеждаемся, что длина гипотенузы, действительно, равна 5 (Рис. 5). 166
Рис. 5 Но обратите внимание, что мы передаём в функцию hypot целые числа, а результат получаем вещественный. Большинство математических функций возвращает число типа float. Будьте внимательны! Случайные числа Мы могли бы ожидать, что модуль math содержит и функцию для генерации случайных чисел, но его там нет - для таких чисел в Питоне имеется отдельный модуль random, а блоки с функциями из этого модуля находятся на вкладке Random (Рис. 1). Рис. 1 Случайные числа используются в компьютерных играх, в моделировании, в методе Монте-Карло, в рандомизированных и оптимизационных алгоритмах. Если вы хотите использовать случайные блоки, то сразу импортируйте модуль random (Рис. 2). Рис. 2 167
Блок randint (Рис. 3) возвращает случайное число n из диапазона a ≤ n ≤ b. Рис. 3 Чтобы узнать, какое число вернул блок randint, распечатаем его на экране. Если вы играли в русское лото, то знаете, что бочонки пронумерованы от 1 до 90 (Рис. 4). Рис. 4 Программа для получения номера случайного бочонка готова (Рис. 5). Рис. 5 После каждого запуска программы вы будете получать новое случайное число от 1 до 90 включительно. К сожалению, для игры в лото наша программа не годится, потому что числа могут повторяться. 168
Случайные числа, которые генерируют компьютерные программы, на самом деле не случайны, потому что вычисляются по формуле. Правильнее называть такие числа псевдослучайными. Блок randint можно заменить блоком randrange, который действует так же, но максимальное число, которое выдаёт этот блок, на 1 меньше верхней границы диапазона: a ≤ n < b. Если вы хотите получать числа от 1 до 90 включительно, но верхняя граница диапазона должна быть 90 + 1 = 91 (Рис. 6). Рис. 6 Границы диапазона могут быть отрицательными, но верхняя граница должна быть не меньше нижней, иначе программа выдаст ошибку. Блок random выдаёт случайное вещественное число n в диапазоне 0.0 ≤ n < 1.0 (Рис. 6). Если вам нужны вещественные числа из другого диапазона, то используйте блок uniform (Рис. 7). Он возвращает случайное вещественное число n из диапазона a ≤ n ≤ b, если a ≤ b, или из диапазона b ≤ n ≤ a, если b < a. С этим блоком вы получите правильное число, даже если нижняя граница диапазона больше верхней. При каждом запуске программы вы будете получать новые случайные числа. Иногда это бывает неудобно. Например, при отладке программы нужен один и тот же ряд случайных чисел, иначе результаты не с чем будет сравнивать. 169
Рис. 6 Рис. 7 Блок seed получает число, которое инициализирует генератор псевдослучайных чисел. Если аргумент отсутствует, то генератор инициализируется случайным числом. 170
Если вы поставите блок в начале программы, то каждый раз будете получать те же самые случайные числа (Рис. 8). Рис. 8 И наконец, давайте обобщим сведения о модуле random в компактной таблице. Модуль random (Случайные числа) Модуль random служит для генерирования последовательности псевдослучайных чисел, равномерно распределённых в заданном диапазоне. Блоки Описание Возвращает целое число n в диапазоне a ≤ n ≤ b. → int → int 171
 int Возвращает вещественное число n в диапазоне 0.0 ≤ n <1.0. Возвращает целое число n в диапазоне a ≤ n ≤ b - 1. → int Инициализирует генератор псевдослучайных чисел для получения повторяющихся последовательностей случайных чисел. Возвращает min..max-1. целое число в диапазоне → float → float  float 172
Проект Двузначное число https://project.edublocks.org/EzKa Очень часто в задачах по программированию нужно выделять цифры из заданного числа. Мы рассмотрим простейший случай – для двузначных чисел. Последнюю цифру любого целого числа легко получить как остаток от деления этого числа на 10. Первую цифру двузначного числа мы получим, если разделим нацело заданное число на 10 (Рис. 1). Рис. 1 Чтобы получить первую цифру трёхзначного числа, его нужно разделить на 100, четырёхзначного – на 1000, и так далее. Проект Цифры трёхзначного числа https://project.edublocks.org/ux6B Самое сложное в этом проекте – выделить среднюю цифру из трёхзначного числа. Поскольку мы знаем, как найти последнюю цифру любого числа, 173
то среднюю, то есть предпоследнюю цифру нужно просто сделать последней, а для этого нацело разделим число на 10 (Рис. 1). Рис. 1 Проект Найти сотни https://project.edublocks.org/yj8H Пусть дано очень большое число – не меньше тысячи. Нам нужно найти число сотен в нём. Чтобы выделить из многозначного числа последние 3 цифры, нужно найти остаток от деления этого числа на 100. Остальное вы уже знаете и умеете (Рис. 1). 174
Рис. 1 Проект Разноциферные числа https://project.edublocks.org/UNKb У нас есть трёхзначное число sde. Давайте проверим истинность высказывания: Все цифры данного числа различны Так как число трёхзначное, то оно состоит из трёх цифр, которые нужно предварительно из него извлечь. Как это сделать, мы уже подробно разобрали в предыдущих проектах (Рис. 1). Остальные действия очень простые. Если все цифры различны, то ни одна пара цифр не совпадает (Рис. 2). 175
Рис. 1 Рис. 2 176
Проект Четырёхзначные палиндромы https://project.edublocks.org/WrGp Палиндромы – это слова или числа, которые одинаково читаются слева направо и справа налево. Нам нужно проверить четырёхзначное число tsde на палиндромность, то есть определить истинность высказывания: Заданное число – палиндром Процесс извлечения цифр из числа вы уже хорошо изучили, поэтому переходим к логическому выражению. Если число одинаково читается в обе стороны, то число тысяч в нём равно числу единиц, а число сотен равно числу десятков: 1221 tsde В программе много переменных, но алгоритм прост и понятен (Рис. 1). Рис. 1 177
Наша программа работает отлично (Рис. 2). Рис. 2 Проект Где точка? https://project.edublocks.org/dESX У нас есть точка на плоскости с координатами (x, y). Нам нужно поверить высказывание: Точка лежит во второй координатной четверти Прежде всего, найдите на Рис. 1 вторую координатную четверть! Рис. 1 Если точка лежит на ней (включая оси координат), то должны одновременно выполняться условия: x <= 0 y >= 0 178
Логика должна быть железной (Рис. 2)! Рис. 2 Проект Белое поле https://project.edublocks.org/PB7D Шахматная доска раскрашена в 2 цвета. Если внимательно и вдумчиво посмотреть на доску, то можно заметить, что сумма координат белых клеток всегда нечётная (Рис. 1). Рис. 1 179
Пусть в переменной col хранится горизонтальная координата клетки, а в переменной row – вертикальная. Мы имеем клетку с координатами (col, row). Нужно проверить, истинно ли высказывание: Эта клетка белого цвета К сожалению, блоки не позволяют выстраивать сложные конструкции, поэтому приходится вычислять логическое выражение в 2 приёма (Рис. 2). Рис. 2 Зато проверки выполняются просто (Рис. 3). Рис. 3 180
В данном случае проще и правильнее записать логическое условие вручную (Рис. 4). Рис. 4 Обобщение Все арифметические операторы могут быть совмещены с оператором присваивания, в результате чего получаются комбинированные операторы присваивания, которые сначала выполняют арифметическую операцию, а затем присваивают переменной её результат. Для полноценных математических расчётов в Питоне имеется модуль math, а для генерирования псевдослучайных чисел – модуль random. Задания для самостоятельного решения Get Ready! for Standardized Tests Math Grade 3 Решите несколько примеров из книги [Osborne02]: 181
600 – 286 724 −382 9004 − 3957 23.60 − 9.57 6 * 537 Класс Math 1. Напишите программу для вычисления длины гипотенузы по двум известным катетам. Воспользуйтесь для этого теоремой Пифагора. 2. Напишите программу, которая генерирует последовательность очков, которые выпадают на игральном кубике. Продолжите исследования с картами и бочонками лото. Нагибин #268 Запишите в порядке возрастания дроби: 182
Занятие_10. Логические переменные и операторы Логические операторы позволяют изменить порядок выполнения исходного кода программы, реагируя на какие-либо события, происходящие в работающей программе (пользователь нажал кнопку мышки или переменная x получила значение 10). На следующем занятии вы познакомитесь с управляющими структурами, которые активно используют логические выражения. Логический тип Логический тип содержит только 2 элемента: True (истина) и False (ложь), поэтому логические переменные могут принимать только эти два значения. Чтобы определить переменную логического типа, ей нужно присвоить логическое значение – True или False. Логиечкие переменные имеют тип bool (Рис. 1). Рис. 1 Полное название типа bool(ean) происходит от фамилии английского математика и логика Джорджа Буля, поэтому логический тип называют также булевым: 183
Во многих языках программирования, например в C++, значение типа bool может быть преобразовано в значение типа int. При этом считается, что значение False равно нулю, а значение True – единице. В Питоне нужно использовать функцию int для преобразования логических значений в целочисленные. Для преобразования числовых типов в логический тип используйте функцию bool. При этом нулевое значение получит логическое значение False, а все остальные – значение True (Рис. 2). Рис. 2 184
Операторы и операции отношения (сравнения) Операции отношения предназначены для сравнения двух операндов совместимых типов (например, целых и вещественных чисел или строк). Результат всегда имеет логический тип и равен True, если указанное соотношение выполняется, и False - в противном случае. Давайте рассмотрим логические выражения и действие логических операторов отношения. == - оператор равенства Результат сравнения равен True, если операнды равны, и False, если не равны. Не смешивайте оператор равенства == с оператором присваивания = В логических выражениях оператор присваивания недопустим! Создаём две целые переменные x и y, а затем сравниваем их между собой с помощью оператора равенства (Рис. 1). Рис. 1 185
Запускаем программу – она полностью подтверждает наши ожидания (Рис. 2). Рис. 2 7 == 13 → False 7 == 3 → False 7 == 2 + 5 → True То есть значение логического выражения 7 == 13 равно False (ложь), а логического выражения 7 == 2 + 5 – True (истина). Действительно, утверждение, что число 7 равно числу 13 - ложно, а утверждение, что число 7 равно сумме чисел 2 и 5 – истинно. < - оператор сравнения «меньше». Результат сравнения равен True, если первый операнд меньше второго, и False, если больше или равен. Обновляем программу (Рис. 3). Рис. 3 186
Запускаем её и читаем результаты сравнения двух операндов (Рис. 4). Рис. 4 7 < 13 → True 7< 3 → False 7 < 2 + 5 → False <= - оператор сравнения «меньше или равно» (не больше). Результат сравнения равен True, если первый операнд меньше второго или равен ему, и False, если больше. Проверяем, не отходя от кода (Рис. 5). Рис. 5 187
7 <= 13 → True 7 <= 3 → False 7 <= 2 + 5 → True > - оператор сравнения «больше». Результат сравнения равен True, если первый операнд больше второго, и False, если меньше или равен. И здесь всё логично (Рис. 6). Рис. 6 7 > 13 → False 7> 3 → True 7 > 2 + 5 → False >= - оператор сравнения «больше или равно» (не меньше). Результат сравнения равен True, если первый операнд больше второго 188
или равен ему, и False, если меньше. Всё познаётся в сравнении (Рис. 7). Рис. 7 7 >= 13 → False 7 >= 3 → True 7 >= 2 + 5 → True != - оператор неравенства Результат сравнения равен True, если операнды не равны, и False, если равны. В языке Delphi используется более привычная для нас запись оператора неравенства <>. В Питоне, очевидно, знак операции != должен напоминать математический знак неравенства ≠. 189
И опять всё верно (Рис. 8). Рис. 8 7 !=13 → True 7 !=3 → True 7 != 2+ 5 → False Условные логические операции Условные логические операции применяются к логическому типу данных, и результат операции также имеет логический тип. Операция логического отрицания унарная, остальные – бинарные. Для обозначения логических операций используют логические операторы and, or и not. not - оператор логического отрицания НЕ (NOT). Результат операции истинный, если значение операнда равно False, и ложный, если значение операнда равно True, то есть not False → True 190
not True → False Эта логическая операция называется также инверсией. Примеры показывают, что в результате выполнения этой операции истинное выражение становится ложным, и наоборот. Добавим код, который изменяет значение логических выражений сравнения (Рис. 1). Рис. 1 Рис. 2 показывает действие оператора not. Рис. 2 191
not (7 == 13) → True not (7 == 3) → True not (7 == 2 + 5) → False Здесь мы видим, что ложные выражения превратились в истинные, и наоборот. and - логический оператор И (AND). Результат операции тогда и только тогда истинный, когда истинны одновременно оба операнда (Рис. 3). Эта логическая операция называется также конъюнкцией. Рис. 3 Запускаем программу и убеждаемся, что правило действует (Рис. 4). Рис. 4 192
x == 2 + 5 and x < y → True x != y and x <= y → True x == y and x == 7 → False В первом логическом выражении операция сравнения x == 2 + 5 вернёт True, так как переменная x равна 7. Операция сравнения x < y также вернёт True, потому что значение переменной x меньше значения переменной y. То есть после выполнения операций сравнения (а их приоритет выше, чем у логических!) выражение примет вид: True and True → True Поскольку оба операнда имеют значение True, то и значение всего логического выражения равно True, значит, оно истинно. Остальные три выражения разберите самостоятельно! Мы обычно говорим с «пропусками» слов, но при этом прекрасно понимаем, о чём идёт речь. Например: переменная x равна y И меньше семи: x=yИ<7 В программах на Питоне двойные условия записываются так (Рис. 5). Рис. 5 Чтобы не запутаться с приоритетами операций, записывайте операции сравнения в скобках: ((x == 2 + 5) and (x < y)) or - логический оператор ИЛИ (OR). Результат операции истинный, если хотя бы один операнд истинен. Эта логическая операция называется также дизъюнкцией. 193
Для исследования этой логической операции достаточно в предыдущей программе заменить оператор and оператором or (Рис. 6). Рис. 6 Здесь изменилось значение только последнего логического выражения (Рис. 7). Рис. 7 x == 2 + 5 or x < y → True x != y or x <= y → True x == y or x == 7 → True Давайте разбираться, почему это произошло. Значение выражения сравнения x == y равно False, ведь значение переменной x равно 7, а значение переменной y равно 13. Значение выражения x == 7 равно True. Итак, мы получили более простое логическое выражение: 194
False or True Первый операнд ложный, второй истинный – этого достаточно для того, чтобы всё логическое выражение было истинным: False or True → True Побитовые операции В языке Питоне имеются 3 побитовые операции, которые могут быть использованы как с целыми типами данных, так и с логическими. Операции & и | действуют так же, как и уже рассмотренные нами операции and и or, поэтому сразу перейдём к операции ^ (Рис. 1). ^ - логический оператор ИСКЛЮЧАЮЩЕЕ ИЛИ (XOR). Если биты разные, то бит результата равен 1. Если биты одинаковые, то результат равен 0. Эта логическая операция называется также исключающей дизъюнкцией. Рис. 1 195
Запускаем приложение и анализируем полученные результаты (Рис. 2). Рис. 2 1010 1111 ---0101 Сравниваем попарно биты двух чисел справа налево. Биты 0 и 1 – разные, значит, результирующий бит равен 1. Биты 1 и 1 – одинаковые, значит, результирующий бит равен 0. Поскольку в Питоне True эквивалентно 1, а False эквивалентно 0, то мы можем применить побитовую операцию XOR и для логических значений (Рис. 3). Рис. 3 196
Таблица истинности Поскольку условные логические операции встречаются в программировании буквально на каждом шагу, то давайте сведём все правила их выполнения в одну таблицу: Логическое выражение exp1 Логическое выражение exp2 Логическая Логическая Логическая операция операция операция exp1 and exp2 exp1 or xp2 exp1^ exp2 True True True True False True False False True True False True False True True False False False False False Здесь логические операции выполняются так: Логическое выражение exp1 and Логическое выражение exp2 Логическое выражение exp1 or Логическое выражение exp2 Логическое выражение exp1 ^ Логическое выражение exp2 Приоритеты операций Мы уже вспомнили приоритеты арифметических операций, но поскольку операций в Питоне значительно больше, то давайте дополним таблицу, чтобы в дальнейшем вы могли легко находить в ней нужную информацию. В программировании, как и в математике, все операции выполняются в полном соответствии с их приоритетом (старшинством). Операции с более высоким приоритетом выполняются раньше операций, приоритет которых ниже. Если приоритет операций одинаков, то они выполняются последовательно слева направо. Таблица Приоритеты операций Операторы Действия () Выражения в круглых скобках f (x) Вызов функций 197
- Унарные + минус и плюс Операции отрицания и идентификации not Операция логического отрицания * / % Арифметические операции умножения, деления и деления по модулю + - Арифметические операции сложения и вычитания < > <= >= == != Операции отношения Операции равенства and ^ Операция логического И Логического операция ИСКЛЮЧАЮЩЕЕ ИЛИ or Операция логического ИЛИ = *= /= += -= Операции присваивания (выполняются справа налево!) Операторы в соседних строках одного цвета имеют равный приоритет. С помощью круглых скобок можно изменить порядок вычисления выражений. Сначала выполняются операции в скобках. Если внутри скобок имеются вложенные скобки, то вычисления начинаются с самых глубоко вложенных скобочных выражений. Например, арифметическое выражение 10 * (21 / (3 + 4) - 5) выполняется так. Находим самые глубоко вложенные скобки, вычисляем выражение в них и подставляем результат в выражение: 198
10 * (21 / (3 + 4) - 5) → 10 * (21 / 7 - 5) Опять вычисляем выражение в скобках: 10 * (21 / 7 - 5) →10 * (-2) И наконец, выполняем операцию умножения: 10 * (-2) →-20 Вопрос: правильно ли записаны выражения 10 * (-2) и 10 * -2? Собираем из блоков небольшую программу и узнаём, что обе записи верные (Рис. 1). Рис. 1 А ответ, почему это так, вы легко найдёте в Табл. Приоритеты операций. Действительно, приоритет оператора унарного минуса выше, чем оператора умножения, поэтому при вычислении выражения сначала будет выполнена операция изменения знака, а затем умножения. Таким образом, скобки в выражении 10 * (-2) не нужны. Однако следует заметить, что с ними выражение становится более понятным, а это гораздо важнее, чем сэкономить пару скобок! Вычисление логических выражений Бинарные логические операции and и or вычисляются по укороченному способу. Это значит, что они проводятся до тех пор, пока не станет заведомо известно значение всего выражения, после чего вычисления прекращаются. Например, рассмотрим логическое выражение (7 > 13) and (7 < 13) → False 199
Значение первого выражения в скобках равно False, поэтому и результат вычисления всего выражения равен False, даже если второе выражение истинно. Поэтому значение второго выражения вообще не вычисляется. Этот приём не только сокращает время вычислений, но и помогает избегать ошибок в программе. В следующем примере сначала проверяется, не равен ли делитель n нулю. Если n = 0, то дальнейшие вычисления не производятся. Если бы проводилось полное вычисление логического выражения, то при вычислении выражения m/n возникла бы ошибка - деление на нуль (Рис. Рис. 1). Рис. 1 Если n = 1, то n != 0 → True, и тогда выисляется второе выражение m / n > 5 → True. Но True and True → True, что мы и видим на Рис. 2. Рис. 2 200
Совершенно очевидно, что если в операции and первый операнд равен False, то второй операнд вычислять смысла нет, поскольку результат операции всё равно будет равен False. Если в операции or первый операнд равен True, то второй операнд не может изменить результата операции - True. Проект Истина или Ложь? https://project.edublocks.org/QTbm Высказывание – это логическое выражение, которое может иметь 2 значения: • True – истинное высказывание • False – ложное высказывание Пусть нам дано некоторое число num. Высказывание, или утверждение такое: Число num чётное Наша задача – установить, истинно или ложно это высказывание. Высказывание Число num чётное можно записать на языке Питон так: num % 2 == 0 Если целое число – чётное, то оно делится на 2 без остатка. Расставляем блоки – и программа готова (Рис. 1)! Рис. 1 201
Проект Числовая середина https://project.edublocks.org/gVCD Пусть у нас есть 3 целых числа - a, b и c. Нам нужно проверить истинность высказывания: Число b находится между числами а и с На воображаемой числовой оси заданные числа могут располагаться так: a---b---с с---b---а Первая схема описывает ситуацию, когда а – самое маленькое из трёх чисел. Вторая – когда самое большое. Если число b находится между а и с, то в первом случае должно выполняться двойное неравенство: а<b<с Во втором случае неравенство должно быть таким: с<b<а Чтобы учесть оба случая, нужно соединить эти неравенства логической операцией or. В Питоне это сделать очень просто (Рис. 1)! Рис. 1 202
А вот и результаты проверки нашей программы (Рис. 2). Рис. 2 Особенно хорошо проявляется красота Питона в текстовом варианте (Рис. 3). Рис. 3 Проект Только одно число https://project.edublocks.org/7qnr Пусть у нас есть 2 целых числа – a и b, а проверить нам нужно высказывание: Только одно из чисел a и b нечётное Нечётность заданных чисел мы проверяем, как обычно, поэтому простые высказывания будут точно такими же, как и в предыдущих проектах. Вопрос в том, как из них получить сложное высказывание/выражение. Здесь самое время вспомнить о логической операции XOR, которая в Питоне обозначается символом ^: 203
XOR - логическая операция ИСКЛЮЧАЮЩЕЕ ИЛИ Результат операции тогда и только тогда будет истинным, когда один операнд истинен, а другой ложен, во всех остальных случаях результат будет ложным. Из её описания становится понятно, что сложное логическое выражение будет истинным только тогда, когда одно из простых выражений истинное, а второе – ложное. Следовательно, для связки простых логических выражений нужно использовать операцию ИСКЛЮЧАЮЩЕЕ ИЛИ (Рис. 1). Рис. 1 Можно обойтись и без логической операции XOR, если учесть, что два числа должны иметь разную чётность: v = (a % 2 != 0) != (b % 2 != 0) 204
Обобщение Переменные, константы и выражения логического типа bool могут принимать 2 значения: True (истина) и False (ложь). Для сравнения операндов совместимых типов используют операции отношения (равенства), обозначаемые знаками: == - оператор равенства != - оператор неравенства < - оператор сравнения «меньше» <= - оператор сравнения «меньше или равно» (не больше) > - оператор сравнения «больше» >= - оператор сравнения «больше или равно» (не меньше) Результат операций отношения имеет логический тип. К значениям логического типа применяют условные логические операции: not - оператор логического отрицания НЕ (NOT) and - логический оператор И (AND) or - логический оператор ИЛИ (OR) ^ - логический оператор ИСКЛЮЧАЮЩЕЕ ИЛИ (XOR) Операция логического отрицания унарная, остальные – бинарные. Все операции, в том числе и логические, выполняются в соответствии с их приоритетом (см. Табл.). Определить результат условной логической операции вам поможет Таблица истинности. 205
Занятие_11. Управляющие структуры Щёлкни кобылу в нос она махнёт хвостом. Козьма Прутков В 1965 г. итальянцы Бом и Джакопини доказали, что для записи любого алгоритма (а, значит, и программы в целом) достаточно трёх управляющих структур: - следования - ветвления (выбора): if if--else - повторения (цикла): for while for-in Управляющая структура следования – самая простая, она предполагает поочерёдное выполнение операторов, то есть в том порядке, в котором они записаны в программе. Наши первые программы как раз и являются примерами такого последовательного выполнения инструкций. Давайте передадим 3 дружеских привета (Рис. 1). Рис. 1 206
Запускаем программу и видим, что все операции печати выполняются последовательно (Рис. 2). Рис. 2 Сколько бы раз мы ни запускали программу, всегда сначала мы отправим привет России, затем Миру и, наконец, заждавшейся бабушке Удава. Итак, мы написали программу со структурой следования. Вы можете добавить в программу ещё сколько угодно операторов печати, и при этом все они будут выполняться точно друг за другом. Без управляющих структур ветвления и повторения жизнь была бы скучна и однообразна. То же самое и в программах: порядок выполнение операторов должен определяться действиями пользователя и другими факторами. На этот случай в языке Питон имеются три оператора выбора if, if-elif и if-elif-else. Вообще говоря, хватило бы и одного оператора if, но тогда многие программы выглядели бы «неуклюже». Другие управляющие структуры - for, while, for-in – просто незаменимы, когда нужно многократно повторить одни и те же действия. Как и в случае с операторами выбора, для записи алгоритмов достаточно одного оператора цикла while, но во многих случаях структура for более эффективна, а for-in – более удобна. Последовательность выполнения операторов в программе называется потоком управления. 207
Блок-схемы алгоритмов Для наглядного представления алгоритмов часто используются блоксхемы и структурные диаграммы. В литературе на русском языке принято изображать алгоритмы блок-схемами. Блок-схемы состоят из элементов, которые графически могут быть представлены по-разному. Мы примем за основу универсальный язык моделирования (UML, Unified Modeling Language), который обычно используют в объектно-ориентированном программировании для того, чтобы графически показать отношения между классами в сложном проекте. Но и в структурном программировании UML тоже найдётся место. Правда, мы его слегка «подправим», чтобы он больше подходил для наших целей. Вместо элементов языка UML для составления блок-схем вы можете с тем же успехом пользоваться символами, принятыми в ГОСТ 19701-90 (соответствует международному стандарту ИСО 5807-85) Схемы алгоритмов, программ, данных и систем. Всякая блок-схема (или просто схема) состоит, по крайней мере, из трёх элементов: Элемент Назначение Начало программы. Поток управления. Конец программы. Самую простую программу, которая вообще ничего не делает, можно представить такой схемой: Любое действие в программе обозначается прямоугольником. 208
Различают действия пользователя (ввод данных с клавиатуры, нажатие кнопки мышки) и действия приложения. Первые показывают обычным прямоугольником, а вторые – прямоугольником со скруглёнными углами: Назначение Элемент Действие пользователя Действие программы Условный оператор If Если гора не идёт к Магомеду, то Магомед идёт к горе. Магомед Трудно себе представить большую программу, которая обошлась бы без условного оператора if. Условный оператор if называют также оператором единственного выбора. С условными операторами мы знакомимся уже в раннем детстве. Например, строгий отец семейства может изложить свои требования в категоричной форме: Если принесёшь из школы, лишу наследства. А вот мама скажет так: Если ты будешь себя хорошо вести, получишь большую сладкую конфету, иначе не пойдёшь гулять во двор. Более наглядно эти посулы можно изобразить так: если принесёшь из школы двойку останешься без карманных денег если ты будешь себя хорошо вести получишь большую сладкую конфету иначе не пойдёшь гулять во двор 209
Условный оператор if служит для того, чтобы изменять порядок выполнения инструкций в программе в зависимости от некоторого логического условия. Он имеет две формы – сокращённую и полную. Сокращённая форма («папина») может быть с единственной инструкцией: if условие: инструкция Или с блоком инструкций: if условие: инструкция1 . . . инструкцияN Отдельная инструкция или блок инструкций печатаются с отступом от ключевого слова if. После логического условия нужно ставить двоеточие. В рассмотренном нами жизненном примере папина декларация состоит из единственной инструкции останешься без карманных денег. А вот если он не ограничится этим воздействием, но и запретит ребёнку выход в Интернет, то получится блок инструкций. Полную («мамину») форму оператора выбора называют if-else, и она также может включать единственную инструкцию в одной или в обеих ветвях или блок инструкций. Оператор if-else с единственной инструкцией: if условие: инструкция1 else: инструкция2 После ключевого слова else нужно ставить двоеточие, но логическое условие записывать нельзя. С блоками инструкций: if условие: 210
инструкция1 . . . инструкцияN else: инструкцияN+1 . . . инструкцияN+M Оператор if - else называют также оператором двойного выбора. Все инструкции в этих ветвях записываются со сдвигом вправо на несколько позиций. Инструкции в ветвях if и else образуют тело условных операторов if и if-else. Ветви if и else с единственной инструкцией можно записать в одну строку: n = 1 if n == 1: print("n = 1") else: print("n != 1") Но такая форма записи менее наглядна. Условие в этих записях – это логическое выражение, которое может быть заключено в скобки, но обычно этого не делают. Если условие состоит из нескольких выражений, объединённых условными логическими операторами, то довольно часто для наглядности в круглые скобки заключают каждое из них: if ((a==1) and (b==1)): . . . if ((a==1) or (b==1)): . . . Для записи логического выражения можно использовать операторы отношения и сравнения ==, !=, <, <=, >, >= и условные операторы and, or, ^. Логическое выражения может быть либо истинным (условие выполняется, значение равно True), либо ложным (не выполняется, значение равно False). Родительские условные операторы, согласно правилам, следует записать так: если принесёшь из школы двойку:  УСЛОВИЕ 211
останешься без карманных денег если будешь себя хорошо вести: получишь большую сладкую конфету иначе: не пойдёшь гулять во двор  ДЕЙСТВИЕ  УСЛОВИЕ  ДЕЙСТВИЕ1  ДЕЙСТВИЕ2 После ключевого слова else условия быть не должно! Действует условный оператор так. Если условие истинное, то выполняется следующая за условием инструкция или блок инструкций. Ветвь else пропускается (если она есть). Если условие ложное, то следующая за условием инструкция или блок инструкций, а ветвь else выполняется (если она есть). После выполнения условного следующей за ним инструкции. оператора управление передаётся Все условные операторы находятся на вкладке Logic (Рис. 1). Рис. 1 Условный оператор обязательно должен иметь блок if. Условные блоки окрашены в зелёный цвет. Блок if имеет окошечко, в которое нужно пометить логическое выражение. По умолчанию там стоит литерал True, поэтому блок if выполнится обязательно (Рис. 2). Рис. 2 212
Если блок if не выполнится (его логическое выражение ложно), то выполнится блок elif, если его логическое выражение истинно (Рис. 3). Рис. 3 Блоков elif в условном операторе может быть сколько угодно. Они действуют, как блок if. Блок else выполняется только в том случае, если до него не выполнился ни один блок if и elif (Рис. 4). Рис. 4 В операторе if-elif-…-elif-else всегда выполняется только 1 ветвь – та, в которой логическое выражение верное, либо блок else, если все условия ложные. Если блок else отсутствует, то может не выполниться вообще ни одна ветвь условного оператора. Логические выражения составляют из блоков отношения (сравнивания) (Рис. 5) Рис. 5 213
и логических блоков (Рис. 6). Рис. 6 Часто необходимо показать на экране значение какой-либо переменной или узнать, выполняется ли тело условного оператора. Тогда в нужном месте условного оператора достаточно поставить вызов функции print, чтобы получить нужную информацию (Рис. 7). Рис. 7 Так как логическое выражение n == 7 → True, то выполнится функция print в блоке if (Рис. 8). Рис. 8 214
Присвоим переменной n значение 9. Теперь логическое выражение n == 7 → False, поэтому инструкции в блоке if не выполняются, а выполняются инструкции в блоке else (Рис. 9). Рис. 9 В текстовом варианте наша программа выглядит точно так же (Рис. 10). Рис. 10 215
Проект Большее из двух чисел Если мы хотим найти большее (max_num) из двух чисел n1 и n2, то это легко сделать с помощью условного оператора. В бесконечном цикле while предлагаем пользователю ввести два числа n1 и n2, а затем - в зависимости от результата операции отношения > - присваиваем большее значение переменной max_num (Рис. 1). Распечатываем весь процесс на экране (Рис. 2). Рис. 1 Рис. 2 Как вы видите, условный оператор не ошибается. Подумайте, изменится ли работа программы, если мы заменим строгое условие (n1 > n2) нестрогим (n1 >= n2)! 216
В Питоне имеется функция max, которая возвращает большее из двух чисел: Естественно, такая удача бывает нечасто. Если нам достаточно только убедиться, что два числа равны, то сделать это ещё проще (Рис. 3). Теперь программа сообщает нам, равны ли два числа в паре (Рис. 4). Рис. 3 Рис. 4 217
Вложенные условные операторы Если после операторов if или else опять следует условный оператор if (или if-else), то он называется вложенным. В этом случае каждый оператор else относится к предшествующему оператору if с тем же отступом: if условие1: if условие2: . . . else: . . . else: . . . Операторы в каждом условном операторе должны быть записаны с отступом! Конструкцию с двумя следующими друг за другом операторами if if условие1: if условие2: . . . else: . . . легко заменить одним, если оба условия соединить логическим оператором and: if условие1 and условие2: . . . else: . . . Если логических условий много, то они записываются друг под другом: if условие1: . . . elif условие2: . . . elif условие3: . . . 218
elif условие4: . . . else: . . . С помощью вложенных условных операторов мы можем, например, значительно «глубже» анализировать данные, полученные от пользователя (Рис. 1). Рис. 1 219
Эти операторы вы можете записать и «профессионально» (Рис. 2). Обе программы работают правильно (Рис. 3). Рис. 2 Рис. 3 Эти примеры показывают, что условные операторы можно комбинировать множеством различных способов. При этом получаются весьма сложные конструкции. 220
Проект Положительные числа https://project.edublocks.org/okH5 У нас есть 3 числа – a, b и c. Наша задача: определить, сколько среди них положительных чисел. Самое простое решение – проверять условие в операторе if для каждого числа отдельно (Рис. 1). Рис. 1 221
Проект Одно больше другого https://project.edublocks.org/3a2M В этом проекте нам нужно определить, какое из двух заданных чисел больше. Здесь важно не забыть, что числа могут быть равны (Рис. 1). Рис. 1 222
Проект Самое маленькое число https://project.edublocks.org/itBL Даны 3 числа. Нужно найти самое маленькое из них. Если все числа различны, то задача решается очень просто. Однако мы должны учесть, что два или все три числа могут быть равны (Рис. 1). Рис. 1 223
Проект Где точка 2? https://project.edublocks.org/iYEQ В этом проекте нам нужно определить номер координатной четверти, в которой находится точка с координатами (x, y), если она не лежит на осях координат. Мы уже решали задачи на координатной плоскости, поэтому вспомним Рис. 1. Рис. 1 Глядя на него, мы быстро напишем условия принадлежности точки к любой координатной плоскости (Рис. 2). Рис. 2 224
Проект Время года https://project.edublocks.org/icsP Пронумеруем месяцы: январь – 1, февраль – 2, … , декабрь – 12. По номеру месяца нужно напечатать время года: зима – весна – лето – осень. Номера зимних месяцев идут не по порядку: 1, 2, 12. Номера остальных месяцев «правильные». Но если найти остаток от деления номера месяца на 12, то остатки для всех времён года располагаются верно. Воспользуемся этим наблюдением в своей программе (Рис. 1). Рис. 1 225
Обобщение Условные операторы if и if-else позволяют выполнять только тот код, который находится в «верной» ветви. Возможность выполнения (или невыполнения) той или иной ветви этих операторов определяется значением условия – логического выражения. Условные операторы могут быть вложенными. Логические выражения – условия операторов if и if-else - вычисляются по укороченному способу, то есть прекращаются сразу же, как только станет известно значение всего выражения. Блок инструкций – это несколько строк исходного кода с одинаковым отступом. Задания для самостоятельного решения Арифметический калькулятор Напишите приложение Арифметический калькулятор. Он должен складывать, вычитать, умножать и делить числа типа int. В бесконечном цикле пользователь сначала вводит два числа, а затем знак арифметической операции + - * / (тип str). Программа печатает результат выполнения операции. Не забывайте, что на нуль делить нельзя! 226
Занятие_12. Циклы Пилите, Шура, пилите! Паниковский Все операторы ветвления действуют так, что поток управления направлен сверху вниз, как в структуре следования, хотя они и позволяют, в зависимости от выполнения каких-либо условий, «перепрыгивать» через некоторые операторы. Однако очень часто нужно повторить несколько раз одни и те же действия. Например, в некоторых проектах мы использовали бесконечный цикл while для ввода данных с клавиатуры. С помощью цикла for мы легко напечатаем 10 случайных номеров бочонков из русского лото (Рис. 1). Рис. 1 Согласитесь, было бы совсем неостроумно 10 раз добавлять к программе одинаковые блоки (Рис. 2). 227
Рис. 2 А с циклом for код получился коротким и более понятным! Достигнув конца цикла, поток управления «течёт вспять» и возвращается в начало цикла. Таким образом, циклы позволяют изменить порядок выполнения операторов в программе. Примеры циклов можно найти и в повседневной жизни: • времена года (циклически сменяют друг друга весна – лето – осень зима), • время суток (утро – день – вечер - ночь), • фазы Луны, • вращение планет вокруг Солнца и Солнечной системы вокруг центра Галактики, • спортивные состязания, 228
• учебный год, • режим дня, • дыхание и кровообращение, • часы, • биоритмы активности человека – можно даже утверждать, что уникальны именно неповторяющиеся события, а не циклические. Цикл for Цикл for используется в программах тогда, когда диапазон изменения какой-либо переменной точно известен. В рассмотренном выше примере нам нужно было напечатать ровно 10 чисел, поэтому мы поступили совершенно правильно, выбрав именно этот вид циклов. Цикл for записывается так: for x in range(выражение): инструкция1  Заголовок цикла  Тело цикла инструкция2 . . . инструкцияN  Конец оператора цикла После ключевого слова for записывают: - имя переменной цикла; например, х - ключевое слово in - вызов функции range, которой передают целое число Эта конструкция называется заголовком цикла. После него ставится двоеточие! Далее, с отступом записывают инструкции, которые составляют тело цикла. Последняя инструкция в теле цикла означает конец оператора цикла. 229
Переменную цикла называют также счётчиком цикла (counter), потому что она используется для подсчитывания итераций. Итерацией называют каждое выполнение тела цикла. Переменная цикла имеет числовой тип. В качестве идентификатора переменной цикла обычно выбирают короткие названия, состоящие из одной буквы – i, j, k, l, m, n. Циклические блоки находятся на вкладке Loops (Циклы) (Рис. 1). Рис. 1 Блок для цикла for использует переменную цикла i (Рис. 2). Рис. 2 Там же есть блок для переменных цикла. Вы можете вставить этот блок в заголовок цикла (Рис. 3) или создать новую переменную цикла. Для этого вызовите контекстное меню на блоке и щёлкните по строчке New variable… (Рис. 4). Соберите из блоков вот такую программу, запустите её и посмотрите результат её работы (Рис. 5). 230
Рис. 3 Рис. 4 Рис. 5 В теле цикла находится вызов функции print, которая распечатывает текущее значение переменной цикла i. Мы передали функции range число 10. В данном случае это число повторов выполнения инструкций в теле цикла, или число итераций. Вы можете пересчитать напечатанные числа и убедиться, что тело цикла выполнено точно 10 раз, а переменная цикла последовательно получила значения от 0 до 9. 231
Если значение переменной цикла в теле цикла не используется, то принято обозначать переменную цикла знаком подчёркивания. Такое имя указывает программисту, что цикл просто выполнится заданное число раз. Например, мы так можем 10 раз послать приветы (Рис. 6). Рис. 6 Но чаще значение переменной как-то используется в теле цикла, и не всегда удобно, чтобы переменная цикла получала последовательные значения, начиная с нуля. Тогда в функцию range следует передать 2 числа: range(a, b) Первое число a – это начало диапазона, второе b – конец диапазона. Важно: переменная цикла i последовательно получит значения a ≤ i < b. То есть последнее значение переменной цикла будет равно b – 1. Такое поведение функции range может привести к ошибкам. Если вы хотите, чтобы переменная цикла получила значение конца диапазона b, то сразу добавьте к концу диапазона единицу: range(a, b + 1) Давайте напечатаем первый десяток натуральных чисел. Отлично получилось (Рис. 7)! Рис. 7 232
Ради эксперимента и для углубления знаний, давайте проверим, как работает цикл for, если верхняя граница диапазона меньше или равна нижней (Рис. 8). Рис. 8 Если вы запустите эти программы, то они ничего не напечатают. Это значит, что тело цикла не выполнится ни разу. Если вы хотите, чтобы переменная цикла получала значения с некоторым шагом, то его следует указать при вызове функции range: range(a, b, step) Давайте напечатаем первый десяток чётных чисел. Значение шага должно быть равно двум (Рис. 9). Рис. 9 Нулевой шаг задать нельзя, а вот отрицательный можно. Но если вы запустите эту программу, то она ничего не напечатает (Рис. 10). 233
Рис. 10 Чтобы понять, почему так происходит, давайте напечатаем чётные числа задом наперёд (Рис. 11). Рис. 11 Из этого примера видно, что при отрицательном шаге верхняя граница должна быть меньше нижней. В противном случае тело цикла не выполнится ни разу. Поэтому, если вы используете в цикле for отрицательный шаг, то будьте внимательны! С помощью цикла for и условного оператора if уже можно писать интересные проекты! 234
Проект Кролики и фазаны Эту древнюю задачу до сих пор решают в средней школе: У фазанов и кроликов 62 ноги и 19 голов. Сколько фазанов и кроликов? На сайте http://festival.1september.ru/articles/569698/ вы найдёте такую разновидность этой китайской задачи с подробным разбором её решения: Сегодня на уроке мы вновь встретимся с вами с хорошо известной вам задачей про фазанов и кроликов (задача выводится на доску “В клетке находятся фазаны и кролики. Известно, что у них 35 голов и 94 ноги. Узнайте число фазанов и число кроликов”), но если раньше мы её решали арифметическим способом, то сегодня будем её решать с помощью уравнений и даже системы уравнений. Решите её самостоятельно! Поскольку ни число голов, ни число ног в программе не изменяется, то для их хранения мы объявляем константы для числа голов (heads) и ног (legs) (Рис. 1). Рис. 1 235
С тем же успехом в задаче можно обойтись и числовыми литералами 19 и 62, но они ничего не говорят о их назначении. Не каждый знает, где у фазанов heads, а где legs, поэтому мы прокомментировали эти блоки. Чтобы добавить к блоку комментарий, вызовите на нём контекстное меню и щёлкните по строчке Add Comment (Рис. 2). Рис. 2 В области редактирования появится пустой текстовый блок. Его можно перемещать мышкой и, ухватившись за угол, изменять размеры (Рис. 3). Рис. 3 Наберите с клавиатуры текст комментария (Рис. 4). Рис. 4 У левой границы блока с комментарием появляется кнопка, которая скрывает/показывает комментарий на экране (Рис. 5). 236
Рис. 5 Удалить ненужный комментарий можно из контекстного меню блока или нажав кнопку с бумажной корзиной в правом верхнем углу блока с комментарием (Рис. 6). Рис. 6 Кнопка-переключатель при этом исчезнет (Рис. 7). Рис. 7 Обратите внимание, как записываются комментарии в текстовой программе (Рис. 8). Рис. 8 Максимальное число кроликов (Rabbits) находим целочисленным делением общего числа ног на 4 (у кролика 4 ноги, или лапы) (Рис. 9). 237
Рис. 9 Минимальное число кроликов равняется нулю - тогда все головы и ноги принадлежат только фазанам. Теперь мы должны перебрать все возможные числа для поголовья кроликов в цикле for. Ясно, что переменная цикла i должна изменяться в диапазоне 0..maxRabbits. Число фазанов (Pheasants) мы найдём, вычтя из общего числа голов число кроликов, то есть i. У i кроликов i*4 ноги, а у nPheasants фазанов - nPheasants*2 ног. Когда сумма ног совпадёт с требуемой (LEGS), мы печатаем ответ. В целом исходный код программы может быть таким (Рис. 10). Запускаем программу и читаем ответ на задачу: кроликов было 12, а фазанов – 7 (Рис. 11). Такой способ решения задач, не требующий тяжких раздумий, называется в программировании методом грубой силы (brute force), или полным перебором (exhausive search) Как вы видите, с его помощью вполне можно решать реальные задачи. Его преимущество в том, что он не требует разработки эффективных, но более сложных алгоритмов. Действительно, если задачу можно решить за пару минут, зачем напрасно тратить время на изобретение хитроумных программ! Этот метод широко используется в программировании и с него обычно и начинают решение многих задач. Если же такой способ не позволяет решить задачу за разумное время, тогда прибегают к разработке более эффективных алгоритмов. 238
Рис. 10 Рис. 11 Проект Репетитор В те далёкие времена, когда компьютеров ещё и в помине не было, школьные детки уже решали задачи по математике, что давалось им нелегко. Этот познавательный процесс хорошо описан Антоном Павловичем Чеховым в рассказе Репетитор. Я надеюсь, что вы с удовольствием прочитаете этот рассказ Чехова (а за ним и многие другие) от начала до конца, поэтому мы перейдём непосредственно к задаче: 239
Теперь по арифметике... Берите доску. Какая следующая задача? Петя плюёт на доску и стирает рукавом. Учитель берёт задачник и диктует: - «Купец купил 138 арш. чёрного и синего сукна за 540 руб. Спрашивается, сколько аршин купил он того и другого, если синее стоило 5 руб. за аршин, а чёрное 3 руб.?» Тяготы репетиторского труда мы пропускаем и читаем финал этой арифметической истории: - И без алгебры решить можно, - говорит Удодов, протягивая руку к счётам и вздыхая. - Вот, извольте видеть... Он щёлкает на счётах, и у него получается 75 и 63, что и нужно было. Итак, ответ на задачу известен, и нам только и остаётся, что заменить старые счёты современными, то есть компьютером. Обозначаем длину (length) сукна и стоимость (cost) соответствующими константами (Рис. 1). Рис. 1 На COST рублей можно было купить не более maxBlue аршин синего сукна (Рис. 2). Вы, конечно, заметили, что эта задача принципиально ничем не отличается от кроличье-фазаньей: заменив кроликов и фазанов синим и чёрным сукном, мы быстро выписываем переборный цикл for (Рис. 3). Запускаем программу и получаем верный ответ (Рис. 4). Как видите, решение таких задач на компьютере – дело техники, а вот на счётах – это уже искусство… 240
Рис. 2 Рис. 3 Рис. 4 И последнее замечание. Не беритесь за решение задачи сломя голову! Поищите аналогичные среди уже решённых вами прежде. Небольшая правка исходного кода – и новая задача падёт к вашим ногам… 241
Проект Факториал А теперь решим более серьёзную задачу по вычислению факториалов. Факториал числа n – это произведение всех натуральных чисел от 1 до n включительно. Обозначается восклицательным знаком после числа: 1! 2! 3! n! (читается 1-факториал, 2-факториал, 3-факториал, энфакториал). Для примера распишем факториал числа 6: 6! = 1*2*3*4*5*6 Для хранения факториала нам понадобится переменная типа int. Вполне разумно назвать её factorial. Перед первым использованием её нужно инициализировать единицей, чтобы все последующие вычисления проводились верно (Рис. 1). Рис. 1 Таким образом, текущее значение переменной равно единице. Затем её нужно последовательно умножать на двойку, тройку, четвёрку, пятёрку и шестёрку. Совершенно очевидно, что для этого годится цикл for, переменная цикла i которого изменяется в диапазоне от 2 до 6 (Рис. 2). Рис. 2 242
В теле цикла мы должны умножать текущее значение факториала factorial на текущее значение переменной цикла i и присваивать результат опять же переменной factorial. Для контроля можно печатать все промежуточные произведения на экране. Вот и вся программа (Рис. 4)! Запускаем программу и читаем на экране все факториалы чисел от 2 до 6 (Рис. 5). Рис. 4 Рис. 5 Замечаем, что тривиальный факториал единицы выпал из списка. Если вам это не по душе, то начните цикл умножения с единицы (Рис. 6). В блоках отсутствует комбинированный оператор присваивания *=, поэтому мы можем использовать его в рукописной форме (Рис. 7). Теперь вы можете вычислять факториалы любых чисел, просто подставляя верхнюю границу диапазона в функцию range. Но это несимпатичное решение! Лучше определить переменную num и присваивать ей нужное значение, а в заголовке цикла заменить литерал этой переменной (Рис. 8). Вот теперь всё хорошо (Рис. 9)! 243
Рис. 6 Рис. 7 Рис. 8 Рис. 9 244
Цикл while Цикл while применяют, когда число повторений заранее неизвестно, но имеется некоторое условие, которое позволяет определить момент завершения цикла. Мы уже неоднократно встречались с циклом while, правда, в несколько курьёзной бесконечной форме, когда условие выполнения цикла всегда верное (Рис. 1). Рис. 1 В общем виде цикл while записывается так: while условие: инструкция1  Заголовок цикла  Тело цикла инструкция2 . . . инструкцияN  Конец оператора цикла А работает он так: 1. Проверяется условие выполнения цикла. Как обычно, это логическое выражение, имеющее тип bool. 2. Если оно ложно (не выполняется), то цикл заканчивается, и программа переходит на строчку, следующую за оператором цикла. 245
3. Если оно истинно, то последовательно выполняются инструкции инструкция1, инструкция2, … , инструкцияN в теле цикла. 4. Управление передаётся в п.1. Поскольку условие проверяется в заголовке цикла, то тело цикла может вообще не выполняться – если выражение с самого начала ложно. Оператор while называется оператором цикла с предусловием. Как видите, цикл заканчивается тогда, когда условие станет ложным. А почему изменяется значение логического выражения (условия) в заголовке цикла? – Для этого должны измениться значения переменных, входящих в это выражение. Отсюда следует вывод: цикл while может вообще никогда не закончиться, и программа зациклится навечно, что очень часто и бывает! Всегда следите за переменной (или переменными), входящей в условие выполнения цикла! Если её значение не изменяется, то цикл либо не выполнится ни одного раза, либо будет выполняться бесконечно! Любой цикл for можно преобразовать в цикл while. Например, возьмём типичный цикл for (Рис. 2). Рис. 2 Объявим переменную цикла (Рис. 3). Перенесём логическое выражение в условие цикла while (Рис. 4). 246
Рис. 3 Рис. 4 Новое значение переменной цикла вычисляем в теле цикла (Рис. 5). Рис. 5 Если мы распечатаем текущие значения переменной цикла, то получим те же числа от 1 до 10 (Рис. 6). 247
Рис. 6 А теперь давайте «забудем» о своих обязанностях по изменению переменной цикла и деактивируем блок, в котором изменяется значение переменной цикла while (Рис. 7). Рис. 7 Запускаем программу – и получаем бесконечный цикл (Рис. 8). 248
Рис. 8 Благодаря блоку (Рис. 9) мы сразу обнаруживаем неполадки в нашей программе, но уберите его - и программа «зависнет» по «непонятной» причине. Рис. 9 Пользуясь циклом while, будьте бдительны и не забывайте изменять переменную цикла! Проект Числа Фибоначчи А теперь давайте напишем полезное приложение, которое найдёт все числа Фибоначчи, которые не превышают заданное число num. Пользователь вводит некоторое целое число в диапазоне от 2 до 999999999 (Рис. 1), после чего мы находим числа Фибоначчи (Рис. 2). 249
Рис. 1 Рис. 2 250
Мы не контролируем правильность ввода числа, поэтому могут быть и ошибки! Чтобы понять, как действует в этом примере оператор while, уделим немного времени числам Фибоначчи. Их открыл Фибоначчи (он же Леонардо Пизанский), средневековый математик, внимательно наблюдавший за размножением кроликов. Первые два числа (f1 и f2) равняются 1 (Рис. 3), Рис. 3 а все последующие равны сумме двух предыдущих, то есть третье число – 1 + 1 = 2, четвёртое – 1 + 2= 3, пятое – 2 + 3 = 5 и так далее, до бесконечности: f2 = f1 + f f = f1 f1 = f2 А условие в заголовке цикла while (Рис. 4) Рис. 4 251
проверяет, не достигло ли очередное число Фибоначчи f2 заданного нами предела num (Рис. 5). Рис. 5 Проект Collatz Другой поучительный и занимательный пример цикла while мы получим при решении Задачи Коллаца, или 3n+1. Лотар Коллац (Lothar Collatz, математик из Гамбургского университета), будучи студентом, предположил, что любое натуральное число n можно «превратить» в единицу, пользуясь очень простыми правилами: 1. Если число n чётно, то его следует разделить на 2. 2. Если число n нечётно, то его следует умножить на 3 и добавить единицу. 3. Выполнять правила 1 и 2 до тех пор, пока результат не станет равным 1. 252
Проверено, что для всех n, меньших 700 000 000 000, эта гипотеза верна, но строго она не доказана. Об истории этой проблемы можно прочитать в книге Мартина Гарднера (Martin Gardner, Wheels, Life and Other Mathematical Amusements). Русский перевод этой книги называется Крестики-нолики. Сотрудники Лаборатории искусственного интеллекта при Массачусетском технологическом институте обнаружили, что если для нечётных чисел использовать выражение 3n-1, то для отрицательных чисел получается такой же результат, как и для положительных. 253
Например, для числа n = 3 мы получим такую последовательность: Шаг 1 → 3 Шаг 2 → 10 (тройка – число нечётное, поэтому действуем по второму правилу: 3 * 3 + 1 = 10) Шаг 3 → 5 (десятка – число чётное, поэтому действуем по первому правилу: 10 / 2 = 5) Шаг 4 → 16 Шаг 5 → 8 Шаг 6 → 4 Шаг 7 → 2 Шаг 8 → 1 Число шагов, приводящих заданное число к единице, называют длиной цикла. Наша задача: написать программу, которая умеет находить длину цикла для заданного числа и печатать числовую последовательность на экране. Как обычно, пользователь вводит число num (Рис. 1). Рис. 1 Мы полагаем, что гипотеза Коллаца верна, поэтому во вложенном цикле while смело выписываем условие выполнения цикла (Рис. 2): n != 1 А в теле цикла мы действуем по первым двум правилам и заодно подсчитываем длину цикла (Рис. 3). 254
Рис. 2 Рис. 3 255
Как видите, закодировать алгоритм Коллаца совсем нетрудно. Запускаем программу и проверяем любые числа (Рис. 4). Рис. 4 Как указывает Мартин Гарднер, самое противное из маленьких чисел – это 27, длина цикла которого составляет 111 шагов (Рис. 5). Рис. 5 256
Мне опровергнуть гипотезу Коллаца не удалось, а вам? Вложенные циклы Мы уже не раз встречались с ситуацией, когда внутри одного условного оператора располагался второй. Внутри второго условного оператора можно поместить третий – и так до бесконечности. Точно так же можно сконструировать и вложенные циклы. При этом важно помнить правило матрёшки: всякий внутренний цикл должен целиком находиться внутри внешнего: for …:  Заголовок первого цикла for …:  Заголовок второго цикла for …:  Заголовок третьего цикла ... ...  Конец третьего цикла ... ...  Конец второго цикла ... ...  Конец первого цикла Как всегда, выделяйте отдельные циклы отступами! Вложенных циклов может быть любое количество и это могут быть циклы for и while в любых сочетаниях. Проект Олимпиадная задача Давайте разберём пример решения задачи с помощью вложенных циклов. 257
В своё время на городской олимпиаде по математике я решал такую задачу: Подсчитайте, сколько раз пятёрка входит в представление чисел от 1 до 1000 в виде произведения простых чисел: 2, 3, 5, 7, 11,… (например, 24 = 2 * 2 * 2 * 3; 25 = 5 * 5). Простенькая программа поможет нам решить задачу (Рис. 1). Рис. 1 258
Здесь вы легко найдёте цикл for, в котором перебираются все заданные числа, и вложенный в него цикл while, который и подсчитывает их делители. Если число нацело делится на 5, то мы увеличиваем счётчик на 1, иначе переходим к проверке следующего числа. Олимпиадный «подвох» этой задачи заключается в том, что полученное после деления на 5 число опять может быть кратно 5, то есть его снова нужно проверить. Если это обстоятельство не учесть, то число пятёрок можно было бы подсчитать мгновенно: 1000 : 5 = 200. Таким образом, в первой тысяче чисел ровно 200 делятся на 5. Ещё 40 делятся на 25 (5*5), 8 – на 125 (5*5*5) и одно – на 625 (5*5*5*5) (Рис. 2)! Рис. 2 Бесконечные циклы Жизнь коротка, а циклы вечны! Программистская мудрость Любовь – кольцо, а у кольца Начала нет и нет конца. Песня о зацикливании Мы уже многократно использовали бесконечные циклы while в своих программах. Они очень удобны, когда число повторений тела цикла заранее неизвестно, а логическое выражение очень сложно или громоздко для того, чтобы записать его как условие продолжение цикла (Рис. 1). 259
Рис. 1 Таким образом, бесконечные циклы могут быть полезны, но нередко они возникают непреднамеренно, как следствие недосмотра программиста. Всякий цикл должен содержать условие, при (не)выполнении которого цикл завершается, - сам по себе цикл не закончится никогда, и программа «зависнет». Обычно бесконечные циклы возникают в цикле while, в котором легко забыть об изменении переменной цикла (Рис. 2). Рис. 2 В этом цикле значение переменной n всегда равно начальному, поскольку в теле цикла не изменяется. Результатом такого просмотра будет бесконечный цикл. Другая распространённая ошибка, приводящая к бесконечному циклу – неверное изменение переменной цикла или неправильно записанное логическое выражение. Например, в этом цикле while переменная n изменяет своё значение в каждой итерации, то «не в ту сторону» (Рис. 3). 260
Рис. 3 В итоге переменная цикла никогда не достигнет максимального значения 10, и цикл будет продолжаться до тех пор, пока переменная цикла не переполнится (а произойдёт это очень нескоро). Если логическое выражение в этом цикле верно, то значение переменной цикла n должно увеличиваться от 1 до 10, а не уменьшаться (Рис. 4). Рис. 4 261
Если работа оператора цикла вызывает у вас сомнения, то запишите в его теле «отладочный» оператор (Рис. 5) и проследите, как изменяется переменная цикла (или она вообще не изменяется!). По представленным выше рисункам сразу можно определить, правильно ли работает оператор цикла. Рис. 5 После отладки цикла отладочный оператор можно стереть или деактивировать. Чтобы не нарушить работу цикла этими действиями, всегда следите за отступами! Досрочный выход из цикла Можно выйти? Школьный вопрос Даже полезный бесконечный цикл должен быть закончен. Самый простой, но не самый эстетичный способ – закрыть программу кнопкой . Иногда нужно прервать выполнение цикла до его окончания. Это может быть связано с тем, что мы уже нашли то, что искали. В одном из выпусков киножурнала Ералаш мальчик искал в родительской библиотеке книгу, в которую, по его же словам, он заныкал рубль (в те времена за рубль можно было купить не одну книгу). Процесс поиска можно описать так: while не все книги проверены: достать очередную книгу с полки потрясти её 262
if рубль выпал: закончить поиск Есть несколько способов досрочного завершения циклов. Например, в цикл while можно добавить флаг (переменную логического типа), который будет сигнализировать об окончании работы цикла. Рассмотрим практически бесполезный пример (Рис. 1). Рис. 1 Перед началом цикла мы сбрасываем флаг, и теперь цикл while будет выполняться до тех пор, пока значение флага не станет равным True. Мы сами должны «поднять флаг» в нужный момент. Например, мы отсчитали ровно 10 проходов цикла (переменная n приняла значение 10). Нам этого вполне достаточно, что мы и сообщаем оператору while, который тут же заканчивается и передаёт управление оператору, следующему за блоком while, а на экране мы увидим числа от 1 до 10 (Рис. 2). Всё очень просто. Главное – не забыть на каждой итерации увеличивать значение переменной n. Флаг можно установить иначе (Рис. 3). 263
Рис. 2 Рис. 3 Переменная flg имеет логический тип, поэтому условия while not flag: и while flag: записаны правильно и точно. Допустимы и выражения с оператором сравнения, while flag != True: while flag == True: while flag == False: но они избыточны и употреблять их не следует. Оператор break В Питоне есть и более элегантные средства для прерывания любых циклов - достаточно в нужном месте тела цикла записать оператор break (Рис. 1). Рис. 1 264
Слегка изменим проект Числа Фибоначчи (Рис. 2). Рис. 2 Когда логическое выражение num < 2 станет верным, выполнится блок break. Он прервёт выполнение тела цикла (то есть все инструкции в теле цикла после него в текущей итерации пропускаются) и передаст управление инструкции, следующей за концом цикла. В циклах while и for оператор break действует одинаково (Рис. 3). 265
Рис. 3 Важно отметить, что оператор break прерывает только тот цикл, в котором он находится. Это значит, что для полного выхода из вложенных циклов потребуется соответствующее число операторов break. Добавим в проект Досрочный выход из цикла блоки break (Рис. 4). Рис. 4 266
Запускаем программу – она закончилась, когда выполнилось условие в первом блоке if (Рис. 5). Рис. 5 Оператор continue Таким … не место в нашем классе! Комедия Большая перемена Оператор continue прерывает только текущую итерацию, и весь цикл выполняется с начала. К сожалению, блок continue в EduBlocks отсутствует, поэтому рассмотрим текстовый пример (Рис. 1). Рис. 1 В цикле for переменная i последовательно получает значения 0..9. Если текущее значение переменной цикла i меньше пяти, то функция print не 267
вызывается, а управление переходит в заголовок цикла, где переменная i получает следующее значение. Рис. 2 показывает, что будут напечатаны только такие значения переменной цикла i, которые не меньше пяти. Рис. 2 Операторы break и continue обычно работают в паре с условным оператором if, который проверяет условие прерывания цикла. Оператор break усложняeт логику программы, поскольку каждый цикл должен иметь единственный вход и единственный выход, а указанный оператор добавляет ещё один выход из цикла. Такие конструкции менее понятны и более «опасны», поэтому применяйте их с осторожностью. Какой цикл выбрать? Выбор оператора цикла определяется алгоритмом. Если мы хотим напечатать числа от 1 до 10, то вполне естественно воспользоваться циклом for (Рис. 1). Рис. 1 268
Цикл for легко «имитировать» циклом while (Рис. 2). Рис. 2 Но обычно к циклу while обращаются, когда известно условие прекращения цикла (особенно сложное), но точное число итераций определить затруднительно. Например, нам нужно вычислить арифметический (целый) корень натурального числа num. Мы полагаем, что корень равен 1 – наименьшему натуральному числу. А затем в цикле while проверяем условие: 𝑥 ≤ √𝑛𝑢𝑚 (1) Если num = 1, то это условие выполнено сразу. В противном случае мы добавляем к переменной x единицу и проверяем условие для следующего натурального числа – двойки. И так до тех пор, пока условие (1) не будет выполнено (а рано или поздно это произойдёт). Нас, безусловно, должен насторожить квадратный корень из числа num в условии (1). Действительно, если мы умеем его находить, то больше ничего и делать не нужно. Более того, извлечение квадратного корня – сложная операция, поэтому в программировании условие (1) записывают иначе: x*x ≤ num (2) 269
Поскольку числа x и num неотрицательные, то мы можем возвести неравенство (1) в квадрат и получить условие (2). Теперь кодирование алгоритма не составляет ни малейшего труда (Рис. 3). Проверка показывает, что наш алгоритм хорошо справляется с поставленной задачей (Рис. 4). Рис. 3 Рис. 4 Из числа x мы должны вычесть 1, чтобы получить верный результат. Для сравнения и проверки работы методов мы также печатаем корни, вычисленные методом sqrt из библиотеки math. Если вы захотите получить арифметический корень из больших чисел, то для них следует использовать более хитроумный алгоритм (Рис. 5). 270
Рис. 5 Обобщение В большинстве случаев следует использовать цикл for, особенно когда число итераций известно заранее, а цикл while – если не известно. 271
Всегда следите, чтобы условие продолжения цикла неизбежно принимало такое значение, которое завершает цикл, иначе программа зациклится. Для досрочного выхода из цикла пользуйтесь оператором break. Для досрочного прекращения текущей итерации используйте оператор continue. Задания для самостоятельного решения Циклы 1. В клетку посажены кролики и фазаны. У животных вместе 35 голов и 100 ног. Сколько в клетке кроликов и сколько фазанов? 2. Некто подошёл к клетке, в которой сидели фазаны и кролики. Сначала он сосчитал головы, их оказалось 15. Потом посчитал ноги, их было 42. Сколько кроликов и сколько фазанов было в клетке? 3. В клетке находятся фазаны и кролики. У всех животных 6 голов и 20 ног. Сколько в клетке кроликов и сколько фазанов? 4. Девяти мальчикам и девочкам подарили 60 конфет, причём каждая девочка получила по 7 конфет, а мальчик – по 6. Сколько было мальчиков и сколько девочек? Задача #1 Математическая шкатулка У троих братьев оказалось вместе 9 карандашей. У младшего – на 1 карандаш меньше, а у старшего – на 1 карандаш больше, чем у среднего брата. Сколько карандашей у каждого из братьев? 272
Задача #29 Математическая шкатулка Какое натуральное число в 7 раз больше цифры его единиц? Ответ: 35. Задача Коллаца В книге Олимпиадные задачи по программированию [PC03] предлагается Задача Коллаца (Задача 1.6.1) в несколько ином варианте, чем тот, что мы решили в проекте Collatz. Здесь пользователь задаёт два числа – начало и конец диапазона, а программа должна найти число (или числа!), которое имеет наибольшую длину цикла. 273
Занятие_13. Списки Все числовые типы и логический тип bool относятся к простым типам данных, поскольку переменные этих типов содержат единственный элемент указанного типа. Дальше мы будем изучать сложные (составные) типы данных – списки, строки и классы. Мы уже печатали 10 случайных чисел. Пусть нам нужно не только напечатать эти числа, но и сохранить для дальнейшего использования в программе. Мы знаем, что для хранения целых значений используются переменные типа int, но теперь нам потребуется не одна переменная n, а десять! Причём мы не сможем присвоить им значения в цикле – придётся искать «личный подход»! Поскольку все переменные имеют сходное назначение, то мы дадим им одно имя, но, чтобы отличать их друг от друга, добавим ещё и порядковый номер (Рис. 1). Рис. 1 274
Нумерацию переменных программировании. мы начинаем с нуля, как принято в Сохранив значения переменных в памяти, мы можем пользоваться ими в любое время и для разных целей. Например, для того, чтобы найти максимальное и минимальное значения, вычислить среднее арифметическое или сумму. Такие задачи часто приходится решать в математике, физике, статистике и в школьной жизни – при выведении оценок за четверть или за год. Как видите, полезно хранить данные для их дальнейшего использования. Однако есть и неудобства при таком способе хранения – для каждого значения нужно иметь отдельную переменную с собственным идентификатором. Объявлять такие переменные и пользоваться ими сложно. Например, мы не можем инициализировать или напечатать их значения в цикле. Чтобы найти сумму всех значений, нам нужно перечислить в выражении все идентификаторы (часть из них я для краткости заменил многоточием): sum = n0 + n1 + n2 + n3 + . . . + n9 Для 10 переменных это ещё небольшая проблема, но ведь бывают списки из сотен и тысяч значений! Естественно, для таких случаев совершенно необходим новый тип данных, который объединял бы в одно целое несколько переменных одного и того же типа, имеющих сходное назначение. Такой тип данных можно найти во всех языках программирования, и называется он списком. Список – это набор (коллекция) объектов (элементов), каждый из которых имеет свой номер в этом наборе (индекс). По-английски массив называется list. Примерами списков могут служить: • квартиры в доме • бирки в раздевалке • семечки в подсолнухе 275
• патроны в магазине • кильки в томате • ученики в классе • слова в словаре • цвета в радуге • пальцы на руке • солдаты в шеренге • бочонки русского лото, шары в спортлото, номера домов – они уже пронумерованы, то есть даже номера элементов (индексы) проставлены! Создание списков Все списочные блоки находяися на вкладке Lists (Рис. 1). Рис. 1 Чтобы создать список, редактирования (Рис. 2). перетащите верхний блок в область 276
Рис. 2 По умолчанию список получит имя myList, но лучше его сразу переименовать (Рис. 3). Рис. 3 Создать список можно двумя способами – без инициализации (с отложенной инициализацией) и с инициализацией. Объявление списка состоит из имени списка, знака присваивания значения и парных квадратных скобок (Рис. 4). имя_списка = [] 277
Рис. 4 Имя списка – это любой допустимый идентификатор. После объявления списка создаётся переменная типа list (Рис. 5). Рис. 5 Но список пуст – в нём нет ни одного элемента (Рис. 6). Рис. 6 Определение списка – это явная инициализация при создании. Для инициализации элементов списка в квадратных скобках через запятую записывают список значений. По умолчанию список содержит 4 элемента (Рис. 7). 278
Рис. 7 Вы можете удалить все или некоторые элементы списка или дополнить его новыми элементами (Рис. 8). Рис. 8 Из этого примера видно, что элементы списка могут быть разных типов. Обращение (доступ) к элементам списка Номера элементов в списке начинаются с нуля. Поэтому первый элемент списка имеет нулевой индекс, а последний – на единицу меньше числа элементов в массиве. Такой способ нумерации элементов массива часто приводит к ошибкам, потому что для нас естественнее считать, что первый элемент имеет индекс 1, а не 0. 279
Поскольку все переменные в списке (элементы) пронумерованы, то к каждому элементу списка можно обратиться по его индексу. Для этого нужно указать имя списка, а затем индекс нужного элемента в квадратных скобках. Например, если мы объявили список list_num, то: list_num[0] – это переменная любого типа, которая имеет в списке индекс 0 (первый элемент списка). list_num[5] – шестой элемент списка. Индекс можно задавать не только константой, но и любым допустимым выражением, которое имеет тип int: nums[2 + 2*3] – элемент массива с индексом 8 n=3 nums[n + n*5] – элемент массива с индексом 18 Для доступа к элементам списка найдите на вкладке Lists этот блок (Рис. 1). Не забудьте изменить имя списка (Рис. 2). Рис. 1 Рис. 2 list_num[3] – это переменная того же типа, что и элемент с индексом 3 в списке. Значение переменной равно значению этого элемента. Если мы распечатаем значение переменной из списка list_num, то получим 4 (Рис. 3). Легко проверить, что это значение элемента списка с индексом 3. Рис. 3 280
Если индекс элемента массива выходит за допустимые границы (например, индекс списке 6 в нашем примере (Рис. 4)), то возникает исключение (Рис. 5) и работа программы прекращается. Не забывайте, что индекс последнего элемента в списке на единицу меньше числа элементов в списке! Рис. 4 Рис. 5 Индекс должен иметь тип int. В противном случае (Рис. 6) Редактор кода выдаст ошибку (Рис. 7). Рис. 6 Рис. 7 Тогда нужно явно преобразовать тип float к типу int (Рис. 8). Рис. 8 Допустимый диапазон изменения индексов 0..длина массива - 1. Если индекс списка задаётся константой, то ошибку легко заметить, но когда индекс вычисляется в выражении, то нужно быть очень внимательным! 281
Функция len возвращает длину списка, то есть число элементов в нём. И тогда в цикле for мы легко распечатаем значения всех элементов списка (Рис. 9). Рис. 9 Но есть способ лучше! Оператор цикла for-in для списков Оператор цикла for-in для списков схож с обычным оператором for, но во многих случаях пользоваться им гораздо удобнее. Найдите на вкладке Loops блок for-in (Рис. 1). Рис. 1 Этот блок последовательно перебирает все элементы списка от первого до последнего, то есть переменная цикла х последовательно принимает значения элементов списка. В цикле for-in, как и в других циклах, можно прерывать итерации с помощью операторов break и continue. Добавьте блок for-in к программе (Рис. 2) и запустите её. Блок for-in напечатает все элементы списка, как и блок for (Рис. 3). 282
Рис. 2 Рис. 3 Легко заметить, что оператор for-in удобнее оператора for , ведь нам не нужно знать длину списка. Кроме того, переменная цикла for-in – это значение очередного элемента списка, а переменная цикла for – его индекс. Чтобы получить значение элемента, нужно дополнительно выполнить оператор обращения к элементам списка! Для большего понимания назовём переменную цикла for-in element. Тогда переменная element – это значение элемента списка: нулевого, первого, второго,… Если мы изменим значение переменной цикла element, то значения элементов списка останутся прежними (Рис. 4). Рис. 4 283
Чтобы изменить значение элемента списка, нужно присвоить ему новое значение. Например, увеличим значение всех элементов списка на 1 (Рис. 5). Рис. 5 Если мы хотим изменить значения всех элементов списка, то это можно сделать только в цикле for, но не в for-in. Многомерные списки 284
Кроме рассмотренных нами одномерных списков, мы можем создавать и многомерные списки. Чаще других в программах встречаются двумерные списки. Геометрическими аналогами одномерных списков можно считать линии. В них все элементы списка как бы выстроены друг за другом в одну линию, или строку. Двумерные массивы – это прямоугольники. В Питоне двумерные списки отсутствуют, поэтому нужно создавать списки списков, то есть каждый элемент первого списка – это второй список. Сначала мы создаём список list1 из четырёх элементов с любыми значениями. Затем создаём список list2 с нужными значениями. И наконец, присваиваем всем элементам списка list1 списки list2. Так мы получаем список списков, который имитирует двумерный массив в других языках программирования (Рис. 1). Рис. 1 Каждый элемент списка list1 – это список list2 (Рис. 2). 285
Рис. 2 Так как каждый элемент списка list1 – это список list2, то мы можем получить значение первого элемента списка list2 в первом элементе списка list1 (Рис. 3). Рис. 3 С многомерными массивами мы сталкиваемся в повседневной жизни. Это: Таблица умножения Значения элементов массива – произведения номера столбца и номера строки. Шахматная доска В каждой клетке может стоять чёрная или белая фигура (или пешка), или клетка может быть пустой. Проект Таблица умножения Для знакомства с многомерными списками мы напишем небольшую программу, которая умеет создавать двумерные списки и распечатывать их. 286
Конечно, нам гораздо интереснее напечатать что-нибудь полезное, а не просто абстрактные числа. Например, хорошим упражнением может послужить Таблица умножения. Конечно, если нам нужно только напечатать таблицу умножения, то мы обойдёмся и без списка, но вдруг она понадобится нам для какой-нибудь программы? Для начала давайте красиво напечатаем таблицу умножения (Рис. 1). Рис. 1 Теперь нам нужно создать 2 списка. Список list1 – это готовая таблица умножения. Изначально он пустой. Список list2 – это строка таблицы умножения. Этот список мы очищаем в начале внешнего цикла for (Рис. 2). 287
Рис. 2 Во внутреннем цикле for мы добавляем числа-строки в список list2 точно так, как мы добавляем новые строки к строковой переменной str (Рис. 3). Рис. 3 Когда внутренний цикл for закончит работу, в списке list2 окажутся все числа для текущей строки. Добавляем эту строку к списку list1 (Рис. 4). 288
Рис. 4 Для проверки списка списков распечатываем его элементы. На Рис. 5 хорошо видно, что в списке списков list1 содержатся правильные числа (Рис. 6). Рис. 5 Рис. 6 Давайте закончим «списочное» занятие проектом, в котором списки играют ведущую роль! Проект Лото Наша новая программа с успехом заменит лототрон, то есть будет случайным образом выбирать 6 чисел из 49. 289
Зададим соответствующие константы (Рис. 1). Рис. 1 При необходимости вы просто исправите значения констант и сможете играть в другую разновидность лото, например 5 из 36. Для хранения выбранных чисел нам потребуется список. Действительно, если мы просто выберем NUM_NUMS случайных чисел, то они могут повториться, а это в реальном лото невозможно. Объявляем список для «шаров». Функция range(1, MAX_NUM + 1) возвращает список чисел 1..49 (Рис. 2). Рис. 2 Распечатываем список num_list и убеждаемся, что все «шары» на месте (Рис. 3). Итак, мы загрузили все шары в лототрон, и теперь нам нужно запустить его, чтобы шары перемешались. Поскольку у нас не настоящие шары, а только числа, то мы должны сами их перемешать. Для этого имеется блок random.shuffle (Рис. 4). 290
Рис. 3 Рис. 4 Если ему передать список, то он тщательно перемешает все числа в этом списке (Рис. 5). Рис. 5 291
Теперь все шары-числа хорошо перемешаны (Рис. 6). Рис. 4 Теперь достаточно распечатать первые 6 чисел из списка. Чтобы взять первые 6 (NUM_NUMS) чисел из списка, нам нужно сделать срез: num_list[:NUM_NUMS] Если перед NUM_NUMS поставить двоеточие, то мы и получим срез из первых 6 чисел. То же самое мы можем сделать и с блоками (Рис. 5). Рис. 5 292
Распечатываем срез и получаем 6 чисел для очередного розыгрыша (Рис. 7). Рис. 7 Если вы запустите программу ещё раз, то получите другой набор чисел (Рис. 8). Рис. 8 Обобщение Список - это сложный (составной) тип данных, предназначенный для хранения значений разного типа. Эти значения называются элементами списка и имеют порядковые номера – индексы, - начинающиеся с нуля. Прежде чем пользоваться списком, его нужно объявить: Или определить, то есть совместить объявление списка с его инициализацией. При явной инициализации в фигурных скобках через запятую записывают список значений: 293
Обратиться к элементу списка (для получения значения или для его изменения) можно по его индексу. Для этого нужно указать имя списка, а затем индекс нужного элемента в квадратных скобках: Для перебора элементов массива удобно пользоваться циклом for-in. Если же значения элементов требуется изменить, то это можно сделать в цикле for. Размерность списка может быть любой. Чаще всего в программах используются одномерные списки, а из многомерных - двумерные и трёхмерные. Задания для самостоятельного решения Списки 1. Обычно результаты розыгрыша лото публикуют так, что номера шаров следуют в порядке возрастания. Научите этому наше приложение Лото! 2. Что нужно изменить в проекте Лото, чтобы программа могла играть в лото 5 из 36? 3. В русском лото вместо шаров используют 90 бочонков, пронумерованных от 1 до 90. Обучите наше приложение Лото доставать бочонки из мешка! 294
Занятие_14. Функции Функция - это именованный блок кода, который обрабатывает данные и возвращает результат в вызывающий код (или ничего не возвращает). Функция может иметь параметры, которые записываются в круглых скобках после имени функции. При вызове функции вместо параметров подставляют значения, которые называются аргументами. Все «функциональные» блоки находятся на вкладке Definitions (Рис. 1). Рис. 1 Определение функции начинается с ключевого слова def (вы, конечно, догадались, что это сокращение от слова definition - определение). За ним следует имя_функции, пара круглых скобок, в которых могут быть записаны параметры. Заголовок функции завершает двоеточие (Рис 2). Все инструкции внутри определения функции образуют тело функции и записываются с отступом. Рис. 2 Чтобы вызвать функцию, нужно написать её имя, а в круглых скобках если это необходимо – аргументы (Рис. 3). Известная вам функция print печатает сообщение на экране. Но если аргумент отсутствует, то просто переводит строку. Эта функция ничего не возвращает. Все функции относятся к классу function (Рис. 4). 295
Рис. 3 Рис. 4 Некоторые функции возвращают значение. Например, функция input возвращает строку, которую ввёл пользователь с клавиатуры (Рис. 5). Рис. 5 Объявите переменную plus, которую вставьте как идентификатор функции в блок def. В эту функцию мы передадим 2 числа, а она вернёт нам сумму этих чисел. Сами числа – это аргументы, а в заголовке функции 296
нужно записать параметры – это имена локальных переменных внутри функции. Назовём их просто a и b, как это принято в математике (Рис. 6). Рис. 6 Объявите переменную res и присвойте ей значение – сумму двух чисел (Рис. 7). Рис. 7 Чтобы вернуть вычисленное значение, используем блок return (Рис. 8). Если вы запустите программу, то она ничего не сделает: определение функции – это неисполняемый блок кода до тех пор, пока функция не будет вызвана. Чтобы увидеть результат работы функции, вызываем её внутри функции print (Рис. 9). Функции plus нужно передать числа или числовые переменные. Мы передаём 2 целых числа – 11 и 12. Запускаем программу, и она печатает верную сумму этих чисел (Рис. 10). 297
Рис. 8 Рис. 9 Рис. 10 Обратите внимание, что после вызова функции в инструкцию подставляется возвращаемое значение, то есть функция print после выполнения функции plus превратится в print(23), поэтому и напечатает это число. Также обратите внимание, что вместо переменных a и b в блок res подставляются текущие значения этих переменных, то есть те числа298
аргументы, которые мы подставили вместо параметров при вызове функции (Рис. 11). Рис. 11 Формальные и фактические параметры Если функция получает информацию (данные) при её вызове, то в круглых скобках записывают список параметров. В списке параметров через запятую перечисляют их имена. Параметры, записанные в скобках, называются формальными. Они определяют имена локальных переменных, используемых в теле функции. Никакого значения эти переменные не имеют – они получат его при вызове функции, когда вместо формальных параметров будут подставлены фактические параметры, или аргументы. Внутри функции формальные параметры ведут себя точно так же, как локальные переменные, инициализированные переданными в функцию значениями. Аргументами могут быть литералы, выражения и отдельные переменные. Имена переменных-аргументов могут совпадать с именами параметров, но могут и не совпадать. В любом случае в функции будут созданы другие переменные. Поскольку эти переменные локальные, то они перекрывают любые другие переменные с теми же именами и будут уничтожены после завершения функции. Другие переменные, объявленные вне функции, не изменяются. В функцию plus можно передавать любые числа – положительные и отрицательные, целые и вещественные. Результат всегда будет верным (Рис. 1). Вы даже можете передать 2 строки, потому что для строк определена операция сложения (конкатенации) (Рис. 2). А вот строку и число складывать нельзя, поэтому при таких вызовах вы получите сообщение об ошибке (Рис. 3). 299
Рис. 1 Рис. 2 Если в функцию передать меньше аргументов, чем параметров, то программа напомнит вам, что в функцию следует передать 2 аргумента, а не один (Рис. 4). 300
Рис. 3 Рис. 4 Подумайте, что произойдёт, если в функцию передать больше аргументов, чем параметров. 301
Проект Параметр-список https://project.edublocks.org/pdB2 До сих пор мы передавали в функции значимые типы или строки, которые ведут себя при передаче, как значимые типы. Давайте попробуем передать в функцию ссылочный тип, например, список (Рис. 1). Рис. 1 Сначала программа распечатывает список lst, затем вызывает функцию inc, которая добавляет число 1 к каждому элементу списка spisok и возвращает изменённый список. Программа снова печатает список lst на экране. На Рис. 1 вы видите, что значения списка lst изменились в функции inc! А всё дело в том, что по умолчанию в функции передаются значения переменных, но значением ссылочной переменной служит адрес объекта. 302
Таким образом, функция inc получает в своё распоряжение ссылку на список, а вовсе не его копию, поэтому легко может изменить сам объект. Вы можете убедиться, что значение числовой переменной num в функции inc не изменяется (Рис. 2). Даже если имена переменной-параметра и переменной-аргумента совпадают, то результат мы получим тот же самый (Рис. 3). Рис. 2 Рис. 3 Необязательные и именованные параметры Некоторые параметры функции могут иметь значения по умолчанию. Например, пусть в нашей функции plus параметр b имеет значение по умолчанию 2022. Если мы вызовем функцию plus с одним аргументом 11, то локальная переменная а получит значение 11, а локальная переменная b - значение по умолчанию – 2022. Функция plus вернёт сумму чисел 11 и 2022 (Рис. 1). 303
Рис. 1 Если же вы вызовите функцию plus с двумя аргументами, то переменная b получит переданное значение – 2023 (Рис. 2). Рис. 2 Важно: необязательные параметры должны следовать за обязательными (если они есть). Нельзя сначала поставить необязательный параметр, а затем обязательный. 304
Пусть теперь необязательным будет первый параметр функции, и мы вызываем функцию с одним аргументом. Программа не сможет определить, какому из параметров присвоить значение 11, и выдаст ошибку (Рис. 3). Рис. 3 При вызове функции аргументы присваиваются соответствующим параметрам, то есть параметр а получит значение 11, а параметр b – значение 12 (Рис. 4). Иногда удобнее вызове функции явно задать значения любым параметрам (как обязательным, так и необязательным), в любом порядке, перечислив их имена и значения при вызове функции. Между именем и значением параметра нужно поставить знак равенства (Рис. 5). Обычно пробелы слева и справа от знака равенства не ставят: b=11, a=12. Поскольку имена параметров перепутать труднее, чем их последовательность, то такой способ вызова функций более надёжный. 305
Рис. 4 Рис. 5 306
Рекурсия - Сказать ли тебе сказку про белого бычка? - Скажи. - Ты скажи, да я скажи, да сказать ли тебе сказку про белого бычка? - Скажи. - Ты скажи, да я скажи, да чего у вас будет, да докуль это будет! Сказать ли тебе сказку про белого бычка? Докучная сказка Из одной функции можно вызывать другие функции. Мы уже так вызывали из функции print функцию input. Но из функции можно вызывать и саму функцию! Этот приём программирования называется рекурсией. Хорошим примером рекурсии в литературе могут служить докучные сказки, которые находчивый русский народ придумал для того, чтобы изводить ими своих врагов, поскольку они никогда не заканчиваются (и те, и другие). Такую рекурсию называют бесконечной. В программах она вызывает «зависание» компьютера до тех пор, пока не будут полностью исчерпаны его ресурсы (точнее, не переполнится программный стек). Естественно, такое поведение программы совершенно недопустимо, поэтому для рекурсивных методов необходимо предусмотреть условие выхода из рекурсии. Рассмотрим функцию print_num, которая печатает заданное число, если оно неотрицательное. Вызываем её с аргументом 1 и получаем на экране это число (Рис. 1). Рис. 1 307
Давайте вызовем функцию print_num из самой функции (Рис. 2). Рис. 2 Так значение параметра num внутри функции не изменяется, то мы живо получим бесконечную рекурсию – до полного исчерпания стека вызовов (Рис. 3). Рис. 3 308
Однако мы недаром записали в начале функции условие (Рис. 4). Рис. 4 Это и есть условие завершения рекурсии: если значение параметра num станет отрицательным, то вызовы функции прекратятся. В нашем примере мы должны уменьшать значение параметра num в каждой итерации. Запускаем программу, и она печатает нам убывающую арифметическую последовательность (Рис. 5). Рис. 5 309
Проект Рекурсивное умножение Рассмотрим курьёзный способ применения рекурсии – умножение двух чисел (Рис. 1). Рис. 1 По сути, здесь вместо умножения двух чисел используется сложение: мы последовательно находим сумму b слагаемых а. Если второе число b большое, то стек переполнится, и никакого результата вы не получите. Если второе число b отрицательное, то произведение будет равно нулю, так что таким способом умножения лучше не пользоваться! 310
Интересный способ умножения (Рис. 1)! Рис. 1. «Сложное» умножение Проект Рекурсивный модуль Другой рекурсивный курьёз – вычисление модуля, то есть нахождение остатка от деления первого числа на второе. Здесь также следует быть осторожным, поскольку деление на нуль вызовет ошибку при выполнении программы (Рис. 1). Рис. 1. Рекурсивный модуль 311
Проект Рекурсивный факториал Теперь пришла пора заняться самым классическим примером рекурсии – вычислением факториала, то есть произведения всех чисел от 1 до заданного: Число Вычисление Факториал 0 1 2 3 4 5 6 По определению 1*1 1*2 2*3 6*4 24 * 5 120 * 6 1 1 2 6 24 120 720 Как следует из таблицы, факториал нуля принимается равным единице! Так как число сомножителей известно, то факториал проще всего вычислить в цикле for (Рис. 1). Рис. 1 312
Здесь нужно выполнить только (n-1) умножение, поэтому функция очень быстро выдаёт результат (Рис. 2). Рис. 2 Переход к рекурсивной функции легче проследить, когда используется цикл while (Рис. 3). Рис. 3 В рекурсивных функциях важно учесть основной случай, когда результат известен заранее и не требует рекурсивного вызова. Если этого не сделать, то рекурсивные вызовы будут продолжаться «бесконечно». 313
На самом деле программа завершится с ошибкой, когда возможности системного стека будут исчерпаны. Из этого следует, что большие факториалы, например, числа 1000 вычислить рекурсивно не удастся по той же самой причине. И это один из недостатков рекурсии. Основной случай называют прекращения рекурсии. также терминальным или условием При вычислении факториала основной случай возникает, когда нужно вычислить факториал нуля. Его вычислять не нужно, поскольку он по определению равен 1. Итак, если функция factR вызывается с нулевым аргументом, то она должна тут же вернуть 1 (Рис. 4). Рис. 4 Если аргумент равен 1, то единицу нужно умножить на факториал предыдущего числа (Рис. 5). В таблице это хорошо видно. В данном случае n = 1, и это число нужно умножить на factR(n-1) = f(0) = 1. В результате функция factR вернёт 1 * 1 = 1. Обратите внимание, что вызов функции с нулевым аргументом factR(0) прекращает рекурсивные вызовы. А что же будет при n = 2? – Так как основной случай не возник, то функция вернёт произведение 2 * factR(1). Но при n = 1 основной случай опять не возникает, и функция снова вернёт произведение 1 * factR(0). И тут, наконец, возникнет основной случай, и функция вернёт 1. Эта 1 будет умноже314
на на предыдущую 1, а та, в свою очередь, на 2. Всё произведение равно 2, и это значение вернёт функция factR. Рис. 5 Чтобы проследить за всеми вызовами рекурсивной функции, дополним её сообщениями (Рис. 6). Рис. 6 315
При n =0 мы получим такие сообщения (Рис. 7). Рис. 7 При n = 1 число сообщений увеличится (Рис. 8). Рис. 8 При n = 2 их станет ещё больше (Рис. 9). При n = 5 сообщения становятся ещё интереснее (Рис. 10). Рис. 10 Хорошо видно, что функция factR вызывает сама себя 5 раз с аргументами 4, 3, 2, 1 и 0. Когда возникает основной случай, все функции начинают возвращать свои значения в вызывающую функцию, где они умножаются на уже полученные значения. 316
Проект Рекурсивные перевороты Более полезный случай применения рекурсии – переворачивание списков (Рис. 1). Рис. 1 Строки – это список символов, поэтому строку мы можем перевернуть аналогично (Рис. 2). Но, как и в первом случае, функция reverse_lst возвращает список – на этот раз список символов заданной строки (Рис. 3). 317
Рис. 2 Рис. 3 Но нам нужна перевёрнутая строка, поэтому пишем рекурсивную функцию reverse_str (Рис. 4). Рис. 4 318
Если перевёрнутая строка совпадает с исходной, то мы нашли словопалиндром, которое читается одинаково слева направо и справа налево (Рис. 5). Рис. 5 Итак, функция reverse_lst возвращает новый список, в котором элементы заданного списка располагаются в обратном порядке. Функция reverse_str действует аналогично, но только для строк, и возвращает строку, записанную задом наперёд. Легко заметить, что обе функции действуют одинаково. Они получают последовательность и номер (индекс) очередного элемента в последовательности. Сначала это первый элемент (с нулевым индексом). Так как этот элемент принадлежит последовательности, то основной случай не наступает, а функция рекурсивно вызывает себя со следующим индексом. И так до тех пор, пока индекс не выйдет за границы по- 319
следовательности. Тогда наступит основной случай, и рекурсивные вызовы прекратятся. Все функции начнут возвращать свои значения, то есть символы строки, начиная с пустого (его вернёт вызов с основным случаем). К нему добавится последний, затем предпоследний. И так далее до самого первого. Так как символы добавляются к пустой строке от конечного к начальному, то в строке res мы получим обращённую строку. Если вы хотите понаблюдать за этим процессом, добавьте функцию print, например, в функцию reverse_str (Рис. 6): Рис. 5. Обратимый процесс Эти же операции можно выполнить и без рекурсивных премудростей (Рис. 6). Рис. 6 320
Но и эту функцию можно заменить простым срезом, который самостоятельно вывернет строку: return lst[::-1] Проект Треугольные числа Ряд треугольных чисел представляет собой простейшую арифметическую прогрессию, поэтому любое треугольное число можно легко вычислить по формуле (Рис. 1): Рис. 1. Tn = ½ n(n + 1) (1) Однако из наших нарисованных треугольников видно, что второе треугольное число получается, если к первому прибавить 2. Третье – если ко второму прибавить 3. Для любого треугольного числа верна такая рекуррентная формула: Tn = Tn-1 + n Из неё хорошо видна прямая аналогия с рекурсивным вычислением факториалов. Нам нужно только заменить умножение сложением (Рис. 2). 321
Рис. 2 Если вам вдруг понадобятся очень большие треугольные числа, то их можно получить из нерекурсивной функции (Рис. 3). Рис. 3 322
Интересно, что сумма двух последовательных треугольных чисел это квадратное число: Tn + Tn+1 = (n+1)2 На Рис. 4 это свойство хорошо видно. Рис. 4 А точное доказательство этого утверждения легко получить из формулы (1), если найти сумму чисел Tn и Tn+1. Менее очевидно такое свойство треугольных чисел: любое целое неотрицательное число можно представить в виде суммы не более трёх треугольных чисел. Это предположение высказал Пьер Ферма в1638 году, а доказал его в 1796 году Карл Гаусс. Проект Рекурсивные числа Фибоначчи Классический пример плохой рекурсии – нахождение чисел Фибоначчи по рекуррентной формуле: Fn = Fn-2 + Fn-1 То есть каждое число Фибоначчи, начиная с третьего, равно сумме двух предыдущих. Первые два числа Фибоначчи: F0 = 0 F1 = 1 Дальше легко продолжить этот ряд: 1, 2, 3, 5, 8, 13, 21, 34, 55, … 323
Этот способ легко реализовать в функции fibo (Рис. 1). Рис. 1 В функции fibo мы учитываем основной случай для двух первых чисел Фибоначчи, которые не вычисляются, а даются в готовом виде. Все остальные числа находим, складывая 2 предыдущих (Рис. 2). Рис. 2 324
Недостаток этого способа в том, что мы не сохраняем уже найденные числа, а каждый раз вычисляем их снова. В результате для больших чисел получается огромная цепочка вызовов функции fibo, и время вычисления быстро растёт. Кроме как для демонстрации рекурсии, это способ никуда не годится. Вообще говоря, если нам нужно получить только заданное число Фибоначчи, то не обязательно хранить в памяти все найденные числа – достаточно двух последних. На каждом шаге предпоследнее число становится последним, а сумма двух последних чисел – текущим числом Фибоначчи, которое становится предпоследним для следующего (Рис. 3). Рис. 3 325
Так как в новой функции fibo_iter остались только простые арифметические операции, то даже огромные числа Фибоначчи находятся практически мгновенно: Число Фибоначчи 1000 = 53575430359313366047421252453000090528070240585276680372187519 41851755255624680612465991894078479290637973364587765734125935 72642846157021799228878734928740196728388741211549271053730253 11855709389770910765232374917909706336993837795827719730385314 57285598238843271083830214915826312193418602834034688 Проект Числовые рекурсии В задачах часто бывает нужно найти, сколько цифр в заданном числе. Мы решим задачу только для натуральных чисел. Нуль и отрицательные числа потребуют дополнительной обработки ввода. Вот основное условие (Рис. 1). Рис. 1 То есть, когда функция get_num_digits получит нуль или отрицательное число, она вернёт нуль, и на этом закончит свою работу. В противном случае натуральное число имеет, по крайней мере, 1 цифру. Если мы разделим нацело заданное число, то оно укоротится на 1 цифру или обратится в нуль. При следующем рекурсивном вызове функция get_num_digits получит либо укороченное число, либо нуль. Если это нуль, то все цифры числа уже посчитаны, в противном случае к сумме цифр добавится ещё 1 (Рис. 2). По этому сценарию можно подсчитать цифры и в нерекурсивной функции. Для ввода чисел и печати длины чисел мы организуем бесконечный цикл ввода чисел, полученных от обеих функций (Рис. 3). 326
Рис. 2 Рис. 3 Другая часто встречающаяся задача состоит в перевёртывании заданного числа. Например, число 123 должно превратиться в 321. 327
Последнюю цифру числа мы легко получим как остаток от деления заданного числа num на 10. Её нужно перенести в начало числа. В числе 123 последняя цифра 3. Она должна занять первое место в перевёрнутом числе, то есть место сотен. И для этого мы должны умножить тройку на 100, а в общем случае на 10 в степени на 1 меньше числа цифр в исходном числе. В числе 123 имеется 3 цифры, значит, тройку следует умножить на 10 в степени 2, то есть как раз на сотню. Подсчитывать цифры мы уже научились, так что с первой цифрой мы успешно справились. Итак, тройка заняла место сотен, и теперь нам нужно повторить операцию на оставшихся двух цифрах исходного числа, то есть на 12. Чтобы его получить, достаточно разделить исходное число на 10 без остатка, а затем рекурсивно вызвать функцию reverse_num для числа 12. Она переставит двойку на место десятков, а от числа останется 1. Она займёт место единиц. Таким образом, число 123 превратится в 321, что нам и нужно. Функция reverse_num реализует разработанный нами алгоритм (Рис. 4). Рис. 4 328
Для переворачивания чисел также существует нерекурсивная версия (Рис. 5). Рис. 5 329
Проект Великолепная четвёрка В книге Algorithmen und Problemlösungen mit C++ (Рис. 1), на страницах 300-302 решается такая задача. Рис. 1 Из четвёрки с помощью трёх простых операций получить любое натуральное число. Операции такие: - добавить 4 в конец - добавить 0 в конец - разделить число на 2, если оно чётное Эту задачу проще решить с конца, то есть заданное число превратить в четвёрку. Тогда и операции станут противоположными: - удалить 4, если она стоит в конце числа - удалить 0, если он стоит в конце числа - умножить число на 2 Вводим любое целое число num, которое передаётся функции solve. Кроме того, она получает сообщения, которые поясняют действие функции. Если число num - четвёрка (основной случай), то решение заканчивается. В противном случае мы рекурсивно выполняем операции над текущим числом num. Если число num заканчивается на нуль, то мы удаляем его. Для этого достаточно разделить число на 10. 330
Аналогично мы поступаем, если число заканчивается на четвёрку. Если число заканчивается на другие цифры, то мы умножаем его на 2. Эти действия мы продолжаем до тех пор, пока число не обратится в четвёрку. Тогда мы печатаем все действия с комментариями в обратном порядке – по мере возврата из вызванных функций. Обратите внимание, что в функции solve операции противоположные, а комментарии «прямые», так как функция напечатает все действия в прямом порядке (Рис. 2). Рис. 2 331
На Рис. 3 вы можете видеть, как работает наша программа. Рис. 3. Оперативно! Проект Рекурсивный тортик В книге Математические изюминки [ХР92], на страницах 9-11 Росс Хонсбергер показывает, как решить такую задачу: Расположим n точек на окружности и соединим их попарно хордами. Предположим, что никакие три хорды не имеют общей точки внутри круга. На сколько областей разобьётся круг этими хордами? Вывод формулы вы можете проследить по книге, нас же интересует только формула как таковая: Здесь: • NR – число областей, на которые хорды разбивают круг 332
• • n – число точек на окружности и - число сочетаний по 2 и по 4 из n Подобную задачу решает и Мартин Гарднер в книге Математические досуги [ГМ72], на страницах 82-87. Она облечена в более занимательную форму: На какое максимальное число кусков можно разделить круглый пирог, если сделать n разрезов, каждый из которых пересекает все остальные? Муж спрашивает у жены: - Милая, на сколько частей разрезать тортик – на шесть или на восемь? Жена отвечает: - Режь на шесть – восемь я не съем… На Рис. 1 вы можете внимательно проследить судьбу тортика, подвергнутого означенным разрезам. Рис. 1. Режем тортик По этим данным с помощью метода конечных разностей легко выводится формула для подсчёта кусков: 333
NR = ½ n2 + ½ n +1 = ½ n(n + 1) + 1 (1) Существует и рекуррентная формула: NR(0) = 1 NR(n) = n + NR(n-1) при n > 0 Давайте в помощь домохозяйкам и кондитерам напишем программу, умеющую подсчитывать куски торта, которые получаются при заданном числе разрезов (Рис. 2). Поскольку в реальной жизни вряд ли придётся разрезать даже самый большой торт на тысячи частей (то есть в пыль!), то для практических нужд вполне достаточно рекуррентной формулы. Рис. 2. Полезная программа 334
Но если вас интересуют и теоретические изыскания в кондитерской науке, то нужно прибегнуть к формуле (1) (Рис. 3). Рис. 3. Очень мелкие кусочки! Проект Рекурсивный тортик 2 Впрочем, хозяйке гораздо интереснее и полезнее знать, сколько нужно сделать разрезов, чтобы получить вполне определённое число кусков торта. Опять бросаемся на помощь домохозяйке! Она задаёт нужное число кусков и получает от функции tortik необходимое число разрезов. В функции tortik нам удобнее пользоваться нерекуррентной формулой. Она получает необходимое число кусков n и начинает последовательно делать num разрезов – до тех пор, пока число кусков не сравняется или не превысит заданного числа кусков (Рис. 1). На Рис. 2 вы можете видеть работу этой во всех отношениях полезной для дома и для семьи программы. 335
Рис. 1. Тоже полезная программа Рис. 2 В некоторых случаях остаются «лишние» куски. Вот почему так важно знать математику и лично нарезать тортики кусками! Обобщение Функция – это именованный блок кода. Функция может возвращать некоторое значение, но может и ничего не возвращать. 336
Функция может не иметь параметров, и тогда круглые скобки после идентификатора функции пустые. Если же функция имеет параметры, то они записываются внутри круглых скобок через запятую – с указанием имени. Такие параметры называются формальными. При вызове функции вместо них следует подставлять фактические параметры, или аргументы. Из функции можно вызывать не только другие функции, но и саму эту функцию. Такие вызовы называются рекурсивными, а сам приём программирования – рекурсией. Чтобы избежать бесконечной рекурсии, необходимо предусмотреть в функции условие выхода из рекурсии. 337
Занятие_15. Решаем задачи Целые числа и их свойства изучает теория чисел, или высшая арифметика. В математических задачах (да и в жизни тоже) нередко нужно быстро определить, делится ли одно число на другое или нет. При этом сам результат деления неважен. У каждого натурального числа имеется, по крайней мере, два делителя - это единица и само число (у единицы они совпадают!). Если других делителей нет, то число называется простым. К ним мы вернёмся немного позже, а сейчас давайте вспомним признаки (то есть правила) делимости. Если делитель – натуральное число, но на него можно разделить любое другое натуральное число – либо нацело, либо с остатком: делимое : делитель = частное + остаток Нас интересует только деление чисел, при котором остаток от деления равен нулю. Признаки делимости чисел Признак делимости на 2 Самый простой признак: число делится на 2 только тогда, когда его последняя цифра равна 0, 2, 4, 6 или 8. Если число делится на 2, то оно называется чётным, если не делится - нечётным. Примеры чётных чисел: 2022, 92, 4, 76, 58. Нечётных: 2023, 91, 5, 77, 61. Иногда этот признак формулируют проще: число делится на 2 тогда и только тогда, когда его последняя цифра чётная. Здесь и далее мы для краткости употребляем слово цифры, но вы должны понимать, что речь идёт об однозначных числах, которые записываются этими цифрами. 338
Признак делимости на 3 Число делится на 3 тогда и только тогда, когда сумма его цифр делится на 3. Например, число 2013 кратно 3, поскольку сумма его цифр равна 6: 2 + 1 + 3 = 6 (при подсчёте нули не учитываем). Если сумма цифр также выражается не однозначным числом, то следует найти сумму его цифр. Если в результате сложения цифр получится одно из чисел 3, 6 или 9, то число делится на 3. В противном случае – не делится. Например, сумма цифр числа 123456789 равняется 45. Число двузначное – опять находим сумму его цифр: 4 + 5 = 9. Получили девятку – значит, исходное число 123456789 делится на три. Признак делимости на 4 Очевидно, что числа, кратные четырём, должны быть чётными. Но этого мало, поэтому мы оставляем от числа только две последние цифры и рассматриваем получившееся двузначное число. Если число сразу двузначное, то ничего отбрасывать не нужно. А если однозначное, то достаточно вспомнить таблицу умножения. Если это двузначное число делится на 4, то и всё число также делится на четыре. Если число сразу двузначное, то ничего отбрасывать не нужно. А если однозначное, то достаточно вспомнить таблицу умножения. Чтобы ещё упростить проверку, сложите число десятков с половиной единиц. Если сумма чётная, то исходное число делится на 4, в противном случае не делится. Проверим число 2022. Число из последних двух цифр равно 22. Оно на 4 не делится, значит, 2022 не кратно четырём. Возьмём другое число 339
4567896. Оставляем две цифры - 96. Складываем 9 с половиной от 6, то есть тройкой и получаем 12. Это число кратно четырём, значит, число 4567896 делится на 4. Признак делимости на 5 Это правило очень похоже на признак делимости на двойку. Число делится на 5, если оно оканчивается на 0 или 5. Признак делимости на 6 Число делится на 6, если одновременно выполняются признаки делимости на 2 и 3. Признак делимости на 7 Хорошего признака делимости чисел на 7 не существует, зато имеется немало достаточно сложных и запутанных. Из них мы выберем один – самый простой и «универсальный». Разбиваем заданное число, начиная с конца, на группы, состоящие из трёх цифр. Например, если мы проверяем число 4567896, то получим три группы цифр: 4 567 896 3 + 2 - 1 + Кстати говоря, в книгах так зачастую и печатают длинные числа, чтобы легче было распознать разряды сотен, тысяч и так далее. В программах на Питоне длинные числа разбиваются на группы знаком подчёркивания: 1_234_567_890 Теперь первое (считаем сзади!) число мы берём со знаком плюс, второе со знаком минус, третье – снова о знаком плюс. То есть знаки плюс и ми340
нус чередуются. Составляем из чисел с их знаками арифметическое выражение и вычисляем его значение: 896 – 567 + 4 = 333 Если результат делится на 7, то и всё число также делится на 7. В противном случае не делится. В нашем примере число 333 на 7 не делится, значит, этот вывод относится и к исходному числу 4567896. Признак делимости на 8 Число делится на 8, если оно чётное, а число, составленное из трёх последних цифр, делится на 8. Так как делить трёхзначное число на 8 тоже нелегко, то можно воспользоваться тем же приёмом, что и в признаке делимости на 4. Тысяча делится на 8 без остатка. Любое число тысяч также разделится на 8, поэтому разряды тысяч и далее в проверяемом числе можно не учитывать. Рассмотрим три последние цифры. К числу, образованному первыми двумя цифрами, добавьте половину единиц, а затем к числу десятков добавьте половину единиц получившегося числа. Если результат - чётное число, то исходное число делится на 8. Проясним этот алгоритм на примере. Начнём с того же числа 2018. Последние три цифры дают двузначное число 18, которое на 8 не делится. Следовательно, не делится и число года. Возьмём другое число 123457928. Оставляем для проверки трёхзначное число 928. Число из первых двух цифр равно 92. Складываем его с половиной единиц - 4 - и получаем 96. Дальше действуем, как в признаке делимости на 4: 9 + 3 = 12. Это число кратно двум, поэтому всё число 123457928 делится на 8. Признак делимости на 9 Этот признак напоминает правило для тройки. Число делится на 9 тогда и только тогда, когда сумма его цифр делится на 9. Раньше мы 341
установили, что число 2013 делится на 3, а сумма его цифр равна шести. Поэтому, согласно этому признаку делимости, на 9 оно не делится. Если сумма цифр выражается не однозначным числом, то следует найти сумму его цифр. То есть действовать так же, как и в признаке делимости на 3. Признак делимости на 10 Ещё проще, чем признак делимости на 5. Число делится на 10 тогда и только тогда, когда оно заканчивается на 0. Например, число 2020 делится на 10, а число 2022 не делится. Признак делимости на 11 Самое любопытное правило; не все его знают, но оно помогает очень просто определить, делится ли, например, номер автобусного билета на 11. Чтобы узнать, делится ли число на 11, нужно подсчитать отдельно сумму цифр, стоящих на нечётных и чётных местах в исходном числе. Если они равны, то число кратно 11. В противном случае нужно из первой суммы вычесть вторую. Если разность делится на 11, то и всё число делится на 11. Если сумма первых трёх цифр равна сумме трёх последних, то такой билет называется счастливым. Например, число 123453 делится на 11, так как 1 + 3 + 5 = 2 + 4 + 3 = 9. А число 123456 не делится (проверьте сами!). Другой признак делимости на 11 полностью совпадает с признаком делимости на 7, но делить сумму чисел нужно на 11. 342
Признак делимости на 12 Число делится на 12 тогда и только тогда, когда одновременно выполняются признаки делимости на 3 и 4. Признак делимости на 13 Признак делимости на 13 тот же самый, что для чисел 7 и 11 (второй способ), но делить сумму чисел нужно на 13. Поэтому я недаром назвал этот признак универсальным. Интересно, что наименьшее число, которое одновременно делится на 7, 11 и 13, равняется 7 х 11 х 13 = 1001, то есть сказочному числу арабских ночей. Признак делимости на 19 Признак делимости чисел на 19 хорошо описан в книге Якова Перельмана Занимательная алгебра. Число делится без остатка на 19 тогда и только тогда, когда число его десятков, сложенное с удвоенным числом единиц, кратно 19. Опять проверим большое число 123457928. Оно содержит 12345792 десятка и 8 единиц. По правилу, получаем: 12345792 + 16 = 12345808 Опять находим число десятков и единиц: 1234580 и 8 – и сумму: 1234580 + 16 = 1234596 И так продолжаем дальше: 123459 + 12 = 123471 12347 + 2 = 12349 1234 + 18 = 1252 1252 + 4 = 1256 125 + 12 = 137 343
13 + 14 = 27 Вывод: число 123457928 на 19 не делится. Добавим к исходному числу шестёрку и проверим сумму на делимость: 123457934 12345793 + 8 = 12345801 1234580 + 2 = 1234582 123458 + 4 = 123462 12346 + 4 = 12350 123 + 10 = 133 13 + 6 = 19 Вывод: число 123457934 на 19 делится. Интересные математические фокусы, связанные с признаками делимости, вы найдёте в книге Мартина Гарднера Математические досуги [ГМ72], Глава 19. Если вы серьёзно интересуетесь свойствами чисел, то прочитайте книгу Н.Н. Воробьёва Признаки делимости [ВНН88]. Проект Делится - не делится? https://project.edublocks.org/94kL Мы вспомнили признаки делимости чисел, без которых человеку обойтись трудно, а вот компьютеру они совсем не нужны, потому что он и без них считает охотно и быстро. C помощью операции деления по модулю можно легко проверить, делится ли одно число на другое нацело или нет. Например, мы хотим узнать, делится ли число 2022 на 3. Собираем из блоков программу (Рис. 1). 344
Рис. 1 Запускаем программу и тут же узнаём, что делится (Рис. 2). То есть нам только и нужно, что проверить остаток от деления. Если он равняется нулю, то первое число делится на второе. Вот и вся премудрость! Рис. 2. Делится – не делится В бесконечном цикле while мы выбираем число, для которого программа найдёт все его делители. Затем мы передаём это число функции solve, которая в цикле for пытается разделить его на числа из диапазона 1..num и печатает на экране все делители заданного числа (Рис. 3). Задавая параметры цикла, мы исходим из того, что любое натуральное число делится на единицу и само на себя. На нуль делить нельзя, отрицательных натуральных чисел нет, а на числа, большие заданного, делить нет смысла. Таким образом, наша программа не только проверяет делимость заданного числа на все числа из диапазона 1..num, но и находит все его делители в порядке возрастания. Для проверки очень больших чисел можно оптимизировать нашу функцию. Достаточно заметить, что заданное число num не может делиться на числа, большие num/2, исключая, естественно, само число. Немного подправим код – и можно находить делители больших чисел (Рис. 4). 345
Рис. 3. Программа в действии 346
Рис. 4. Оптимизированная программа 347
Мы ещё во много раз ускорим поиск делителей, если заметим, что произведение симметричных относительно середины ряда делителей равно заданному числу. Например, для числа 64 мы получили такой ряд делителей: 1 2 4 8 16 32 64 Проверяем утверждение: 1 х 64 = 2 x 32 = 4 x 16 = 8 x 8 = 64 Всё верно! Единственное «неудобство» причиняют восьмёрки – они дважды входят в произведение, поэтому нам следует подумать, как оставить только одну из них. Теперь легко заметить, что нам достаточно найти делители заданного числа в диапазоне 1..√𝑛𝑢𝑚. Вторую половину делителей мы найдём, поделив заданное число на очередной делитель. Для хранения делителей заведём список res (Рис. 5). И вот почему. Для первого делителя – единицы – мы найдём парный делитель, равный заданному числу num, для второго парный делитель равен (num // второй делитель). То есть делители мы напечатаем не по порядку (Рис. 6). Чтобы выправить ситуацию, мы до печати результатов отсортируем список res с помощью функции sort списочного класса, а затем напечатаем делители строго по ранжиру (Рис. 7). Теперь даже для огромных чисел мы мгновенно выписываем все делители (Рис. 8). Для последовательного получения делителей какого-либо числа можно воспользоваться простым генератором: def divisorGenerator(num): for i in range(1, num // 2 + 1): if num % i == 0: yield i yield num 348
for i in divisorGenerator(num): print(i, end=' ') Рис. 5 Рис. 6. Неупорядоченные делители 349
Рис. 7 Рис. 8. Молниеносное нахождение делителей 350
Задачи с сайта Проект Эйлер В Интернете нетрудно найти сайты, на которых предлагаются задачи для самостоятельного решения. Вот очень известный сайт Project Euler (Рис. 1): https://projecteuler.net Рис. 1 Сейчас на сайте опубликовано около 800 задач. Первые задачи не очень сложные, так что вполне по силам и начинающим любителям программирования. Условия задач даны на английском языке, поэтому не всем могут быть понятны. Но есть и русскоязычная версия проекта (Рис. 2): http://euler.jakumo.org Рис. 2 351
Проект Задача 1 с сайта Проект Эйлер https://project.edublocks.org/HjG2 Задача номер 1 (Problem 1) называется Multiples of 3 and 5: If we list all the natural numbers below 10 that are multiples of 3 or 5, we get 3, 5, 6 and 9. The sum of these multiples is 23. Find the sum of all the multiples of 3 or 5 below 1000. Найдите сумму всех натуральных чисел, которые: меньше 1000 делятся без остатка на 3 или на 5 Вызываем функцию solve для непосредственного решения задачи (Рис. 1). Рис. 1 Поскольку нужно проверить всего 999 чисел, то для решения задачи можно воспользоваться методом грубой силы и просто перебрать их в цикле for (Рис. 2). Делимость чисел на тройку и пятёрку легко установить с помощью операции деления по модулю: если остаток равен нулю, значит, число i кратно трём (или пяти). Все кратные числа добавляем к переменной sum, которая после завершения цикла и будет равна искомой сумме (Рис. 3). Если подумать… Если подумать, то задачу можно решить и без перебора, причём для любого диапазона чисел. Все числа, кратные трём, образуют арифметическую последовательность: 352
3 6 9 12 15 18 . . . (1) Рис. 2 Рис. 3 Аналогично – для чисел, кратных пяти: 5 10 15 20 25 30 . . . (2) Поскольку все члены этих рядов имеют общий множитель, его можно вынести за скобки: 3 (1 2 3 4 5 6 . . .) 5 (1 2 3 4 5 6 . . .) В общем случае: k (1 2 3 4 5 6 . . .) Сумму последовательности натуральных чисел легко найти по формуле: 353
sum(N) = (N+1)N / 2, где N – число членов в последовательности. Если мы знаем максимальное число, которого не превышают члены последовательности, то число членов можно вычислить так: Nk = [max / k] То есть мы должны найти целую часть дроби. Чтобы не обременять себя расчётами, мы напишем функцию, которая возвращает сумму членов заданной арифметической прогрессии (Рис. 4). Рис. 4 В ней мы используем наши формулы. Теперь можно без всякого перебора, сразу найти сумму заданных чисел, кратных трём или пяти (Рис. 5). Рис. 5 354
Запускаем программу. Сумма чисел получилась больше, чем в первом случае (Рис. 6). Рис. 6 Причину недоразумения легко определить, если ещё раз взглянуть на ряды чисел (1) и (2). Мы дважды посчитали числа, которые одновременно делятся на 3 и на 5. Чтобы получить верное решение, необходимо из полученной суммы sum вычесть сумму чисел, кратных 3 и 5 одновременно (Рис. 7). Рис. 7 Теперь мы получаем правильный ответ на задачу (Рис. 8). Рис. 8 Задачу из Проекта Эйлера, безусловно, можно решить полным перебором, но для очень длинного ряда чисел без второго метода не обойтись! 355
Проект Четыре числа https://project.edublocks.org/7ZRy В 1983 году вышла книга The Commodore Puzzle Book: BASIC Brainteasers. Это было в те далёкие времена, когда только начали появляться первые персональные компьютеры. Одним из самых известных был Commodore. Люди в то время были гораздо любознательнее, чем нынче, поэтому книга по решению занимательных математических задач на компьютере была как раз впору и к месту. В этой книге собрано немало задач, которые могут послужить хорошим упражнением и в современном программировании. На странице 4 нас ждёт «дополнительное домашнее задание»: найти максимальное число n, которое при делении на него чисел 1731 5363 7179 9903 даёт одинаковый остаток r. Понятно, что искомое число не превышает наименьшего из этих чисел, то есть 1731. Если n = 1731, то r = 0, но ни одно из остальных чисел не делится нацело на 1731. Значит, нужно проверить число на 1 меньше, чем 1731, то есть 1730: 1731 % 1730 = 1 Но 5363 % 1730 = 173 Опять неудача! Но теперь мы точно знаем, что нужно последовательно вычитать из числа 1731 единицу и находить остатки от деления предложенных чисел на разницу. Когда все остатки от деления совпадут, мы напечатаем ответ (Рис. 1). 356
Рис. 1 357
Проект Совершенные числа https://project.edublocks.org/ooXW В книге Брудно и Каплана Олимпиады по программированию для школьников [БК85] имеется такая задача: 84.3. Совершенные числа. Совершенным называется натуральное число, равное сумме своих делителей, исключая само число. Первое совершенное число равно шести: 6 = 1 + 2 + 3. Второе равно 28 = 1 + 2 + 4 + 7 + 14. Третье – 496, четвёртое – 8128. Следующие совершенные числа уже гораздо больше. Напечатать все совершенные числа, меньшие, чем заданное М. По-английски совершенные числа называются perfect numbers. На сайте The OEIS Foundation http://oeis.org/A000396 вы найдёте последовательность совершенных чисел: 6 28 496 8128 33 550 336 8 589 869 056 137 438 691 328, 23 05 843 008 139 952 128 2 658 455 991 569 831 744 654 692 615 953 842 176 191 561 942 608 236 107 294 793 378 084 303 638 130 997 321 548 169 216 Легко заметить, что первые 4 совершенных числа достаточно маленькие, а затем они стремительно увеличиваются! Из этого наблюдения следует, что первые совершенные числа можно искать методом грубой силы. Практически такой же алгоритм поиска совершенных чисел предлагается и в книге Брудно и Каплана (Рис. 1). 358
Рис. 1 Увы, дальше четвёртого числа с функцией рerfectNumbers мы не продвинемся (Рис. 2). Рис. 2. Несовершенный алгоритм для поиска совершенных чисел 359
Проект Дружественные числа https://project.edublocks.org/zJeF Два (различных) натуральных числа называются дружественными, если сумма всех делителей (исключая само число) первого числа равна второму числу, и наоборот. Первая пара дружественных чисел была найдена несколько тысячелетий тому назад. Это числа 220 и 284. Следующая пара отыскалась только в 1866 году – 1184 и 1210 (но раньше уже были известны другие дружественные числа). Сейчас список дружественных чисел включает миллиарды пар. Напишите программу для их поиска [ЗП88, Задача 560]. Учитывайте, что числа в паре либо оба чётные, либо оба нечётные. Для проверки в таблице приведены первые 15 пар дружественных чисел (Рис. 1). Рис. 1 Сейчас известно более миллиарда пар дружественных чисел, но никто не знает, конечно ли множество дружественных чисел или бесконечно. Нам будет вполне достаточно найти небольшие дружественные числа. Верхнюю границу для поиска дружественных чисел мы задаём при вызове функции amicables (Рис. 2). 360
Рис. 2 Функция amicables необычная для вас. Это функция-генератор, которая возвращает последовательность чисел в заданном диапазоне (Рис. 3). Рис. 3 Первое число пары n1 - это число 1..number. Для каждого из них мы находим сумму делителей n2. Но эта сумма должна быть вторым числом пары. Это так и будет, если сумма его делителей равна первому числу. Чтобы пары чисел не повторялись, мы считаем, что первое число в паре меньше второго (Рис. 4). Оператор yield действует, как оператор return, но функция продолжает выполняться. В цикле for-in мы получаем от функции amicables пары дружественных чисел, пока значение параметра не превысит максимальное число (Рис. 5). Сумму делителей заданного числа подсчитываем в функции sum_factors (Рис. 6). 361
Рис. 4 Рис. 5 Рис. 6 362
Этот способ не очень быстрый, поэтому не ищите большие дружественные числа (Рис. 7). Рис. 7 Проект Назойливый остаток https://project.edublocks.org/Cjoa В книге Бориса Кордемского и Аскера Ахадова Удивительный мир чисел [КА86] вы найдёте немало интересных задач, в том числе и на делимость. На странице 86 авторы предлагают решить задачу Назойливый остаток: Некоторые числа, кратные числу 7, при делении на 2, на 3, на 4, на 5 и на 6 дают остаток 1. Найдите наименьшее из таких чисел. Эта же задача напечатана в книге Фёдора Нагибина и Евгения Канина Математическая шкатулка [Нагибин88], задача 42, страницы 18-19, но в более занимательной форме: Колхозница привезла на рынок для продажи корзину яиц. Продавала она их по одной и той же цене. После продажи яиц колхозница пожелала проверить, верно ли она получала деньги. Но вот беда: она забыла, сколько у неё было яиц. Вспомнила она только, что когда перекладывала яйца по 2, то оставалось одно яйцо; одно яйцо оставалось также при перекладывании яиц по 3, по 4, по 5, по 6. Когда же она перекладывала яйца по 7, то не оставалось ни одного. Помоги колхознице сообразить, сколько у неё было яиц. Бросаемся на помощь бестолковой колхознице и вызываем функцию solve для решения этой головоломки (Рис. 1). 363
Рис. 1 Поскольку речь идёт о натуральных числах, то мы можем начать наши поиски с единицы (Рис. 2). Рис. 2 Если число 1 не является решением задачи, то мы переходим к двойке, к тройке, и так далее – пока не найдётся искомое число num. Так как мы всякий раз добавляем к начальному значению переменной minnum единицу, то вполне разумно делать это в цикле for, в котором переменная num будет играть роль переменной цикла. Обычно к циклу for прибегают тогда, когда число повторов точно известно. В нашем же случае, мы знаем только начало цикла (min = 1), но не знаем, на каком числе он закончится. Впрочем, мы вполне разумно можем предположить, что у колхозницы было не очень много яиц, и задать заведомо большее значение для верхней границы цикла. Так мы организуем почти бесконечный цикл, который прервём сразу же, как только искомое число будет обнаружено. Для этого мы воспользуемся флажком – логической переменной flg. Если очередное число num выдержит все проверки, значение флага останется верным (True), а мы с помощью оператора break прервём цикл for и напечатаем ответ на задачу (Рис. 3). Проверку очередного числа на остаток, равный единице, также можно проводить в цикле, чтобы не выписывать несколько одинаковых условий. Если число num при делении хотя бы на одно из чисел 2..6 не даёт в остатке 1, то мы сбрасываем флажок и прерываем внутренний цикл for (Рис. 4). На Рис. 5 вы видите ответ на эту задачу. 364
Рис. 3 Рис. 4 Рис. 5. Яиц было немало! Не знаю, как вам, но мне интересно, а есть ли ещё и другие числа, которые имеют назойливый остаток? 365
Имея компьютер, мы легко утолим своё любопытство. Достаточно написать новую функцию solve2, которая поразительно напоминает первую версию (Рис. 6). Рис. 6 Тут, конечно, следует учесть, что бесконечный цикл уже не годится, потому что он действительно станет бесконечным, если искомых чисел окажется очень много (а это нетрудно предвидеть). 366
Запускаем программу и видим, что среди первой десятки тысяч натуральных чисел довольно много подходящих под условие задачи (Рис. 7). Рис. 7. Неназойливый список назойливых чисел Также нетрудно подметить такую закономерность. Если обозначить через n номер искомого числа, то все числа с назойливыми остатками можно легко найти по формуле: num = 301 + 420(n-1) Любопытно, что, если решать задачу для чисел, кратных не 7, а большим числам, то это непременно должны быть простые числа. 367
Проект Шестизначное число https://project.edublocks.org/PecD Задача 4 из книги Удивительный мир чисел [КА86], страница 44: Ученику понадобилось написать наибольшее из шестизначных чисел, кратных 11 и чтобы цифра 6 была первой слева. Как надо действовать ученику для быстрого выполнения задания, если признаков делимости на 11 он ещё не знает? Сообщим, что искомое число обладает забавной особенностью: если каждую его цифру повернуть на 180° в плоскости бумаги, оставляя её на прежнем месте, то образовавшееся число окажется дважды кратным 11 (делится на 11 и частное также делится на 11). Выявите ещё одну особенность чисел: найденного и с повёрнутыми цифрами. Как обычно, начинаем решение задачи с вызова функции solve (Рис. 1). Рис. 1 Легко догадаться, что нужно искать решение задачи среди шестизначных чисел, начинающихся с шестёрки (Рис. 2). Рис. 2 368
Причём перебирать числа следует задом наперёд, то есть от большего к меньшему, чтобы сразу же найти наибольшее из всех возможных чисел в заданном диапазоне (Рис. 3). Рис. 3 А вот и ответ (Рис. 4). Рис. 4. Крути-верти По условию задачи, поворачиваем все цифры найденного числа: 699996 → 966669 Проверяем, делится ли перевёрнутое число на 11 * 11 = 121. Это легко сделать в IDLE. Рис. 5 подтверждает: перевёрнутое число делится на 121. Рис. 5. Поделилось! А ещё одной особенностью этих чисел является их палиндромичность – они одинаково читаются и в прямом, и в обратном направлении. 369
Проект Любопытное свойство чисел https://project.edublocks.org/dahC Задача 15 (16 – номер задачи в издании 1996 года) из книги Удивительный мир чисел [КА86], страница 102: Возьмите какое-либо б-значное число, делящееся на 7, например 325 836. Перенесите последнюю цифру в начало записи числа. Образуется новое число 632 583. Оно также делится на 7. Докажите самостоятельно, что таким свойством обладает любое 6значное число, делящееся на 7. Рекомендация. Представьте заданное число так: 7k = = 10а+ 6 (1). Тогда новое число примет вид 100 0006 +а (2). Используя (1), докажите делимость (2) на число 7. Доказать - значит, убедиться, что все 6-значные числа обладают указанным свойством. Это можно сделать «теоретически», то есть с помощью математических выкладок, а можно и «практически» - с помощью метода грубой силы, или полного перебора. Оба способа доказательства можно считать строгими, ведь они исчерпывают все возможные варианты. Поскольку 6-значных чисел совсем немного, то метод грубой силы здесь вполне уместен. Тем более что алгоритмы, построенные на этом методе почти всегда достаточно простые. Традиционно вызываем функцию solve для непосредственного решения задачи (Рис. 1). Рис. 1 В функции solve обозначаем переменными минимальное и максимальное 6-значные числа, которые нам надлежит проверить (Рис. 2). 370
Рис. 2 Флаг flg призван сигнализировать о (не)соблюдении условия задачи: поначалу он установлен в True, но если по ходу проверки нам встретится число, которое нарушает условие задачи, то мы с чистой совестью сбрасываем флаг и прекращаем дальнейшие проверки – гипотеза опровергнута. Если же после испытания всех 6-значных чисел флаг так и останется установленным в True, значит, гипотеза верна. Поскольку диапазон значений проверяемых чисел точно очерчен, то перебирать числа удобнее всего в цикле for (Рис. 3). Рис. 3 Все числа, не кратные 7, пропускаем (Рис. 4). Рис. 4 Всем остальным назначаем проверки. Чтобы перенести последнюю цифру числа в начало, нужно её выделить. Это легко сделать, применив к числу операцию деления по модулю (Рис. 5). 371
Рис. 5 Число из первых 5 цифр найти ещё проще – нужно просто разделить исходное число на 10 (Рис. 6). Рис. 6 При формировании нового 6-значного числа переносим последнюю цифру в начало, что соответствует умножению на 100000. К этому произведению следует добавить 5-значное число из первых пяти цифр исходного числа (Рис. 7). Рис. 7 Эту операцию можно записать более наглядно: 123456 исходное 6-значное число 612345 новое 6-значное число Проверяем условие задачи (Рис. 8). Рис. 8 372
Печатаем на экране результаты проверки (Рис. 9). Рис. 9. Доказали! Так как мы проверили все 6-значные числа, то можем уверенно утверждать, что любое 6-значное число удовлетворяет условиям задачи. Проект Как определил ошибку Чохбилмиш? https://project.edublocks.org/Z5hi Задача 23 (25) из книги Удивительный мир чисел [КА86], страница 57: Чохбилмиш предложил каждому из двух учеников задумать какое-либо шестизначное число и переставить первую цифру в конец записи числа. Одному сказал: «Найди сумму получившихся чисел». Другому сказал: «Найди разность». Ученики выполнили действия и написали: 913 485 и 167 860. Чохбилмиш не знал, какие числа были задуманы учениками, но сразу определил: «Вы оба ошиблись». Как рассуждал Чохбилмиш? 373
В ответе на задачу утверждается, что сумма любого 6-значного числа с другим 6-значным числом, полученным из исходного переносом первой цифры в конец числа, кратна 11 и аналогично полученная разность – кратна 9. Мы можем проверить эти утверждения с помощью полного перебора, тем более что самая трудная часть задачи – перенос цифры – нами уже решена в предыдущем проекте (Рис. 1). Рис. 1 Рис. 2. И здесь всё верно Проверив все 6-значные числа, мы можем с уверенностью констатировать факт: оба утверждения верные (Рис. 2)! 374
Проект Шестизначный перенос https://project.edublocks.org/AtvS Задача 557 из книги Математическая шкатулка [Нагибин88], страница 94: Первая слева цифра шестизначного числа – 1. Если её перенести с первого места в конец числа, сохранив порядок остальных цифр, то вновь полученное число будет втрое больше первоначального. Восстановите первоначальное число. Эта задача отличается от двух предыдущих только тем, что переносить нужно не последнюю цифру, а первую (Рис. 1). Рис. 1 375
Среди 6-значных чисел, начинающихся с единицы, первоначальное число – единственное. Есть ещё одно подобное число, но оно начинается с двойки (Рис. 2). Рис. 2. Перенос закончен Проект Наименьшее число https://project.edublocks.org/G47G В журнале Наука и жизнь, №2 за 1968 год, на странице 57 напечатана такая задача (Рис. 1). Рис. 1 Задача исключительно на сообразительность. Вот журнальное решение задачи (Рис. 2). Рис. 2 Не каждый этим похвальным даром обладает, поэтому мы пишем простенькую программу (Рис. 3). Когда искомое число заведомо небольшое, то его легко найти простым перебором в бесконечном цикле while. Он заканчивается, когда найдено первое число, удовлетворяющее всем условиям задачи (Рис. 4). 376
Рис. 3 Рис. 4. Программирование - удел несообразительных Вопреки ожиданиям наш ответ полностью совпал с «сообразительным» … 377
Проект Трёхзначное число https://project.edublocks.org/EMx1 В книге 600 задач на сообразительность, на странице 112 напечатана задача 41: Трёхзначное число Если от трёхзначного числа отнять 7, то оно разделится на 7; если отнять от него 8, то оно разделится на 8; если отнять от него 9, то оно разделится на 9. Какое это число? Опять задача на сообразительность, которой мы как бы не обладаем, а потому сразу садимся за компьютер и решаем задачу (Рис. 1). Рис. 1 378
Ответ такой (Рис. 2). Рис. 2. Опять смекалки не хватило… Он, безусловно, правильный, но, чтобы его получить, вполне можно обойтись и смекалкой. Действительно, если число n – 7 нацело делится на 7, то и число n кратно 7. Аналогично для чисел 8 и 9. Стало быть, искомое число одновременно делится на 7, 8 и 9. Минимальное число, обладающее такими свойствами равно: 7 * 8 * 9 = 504 Следующее такое число 504 * 2 = 1008, но оно не трёхзначное. Проект Задача Клайва Синклера https://project.edublocks.org/8ZND Давайте решим задачу, который придумал сэр Клайв Синклер (тот самый Синклер, который сделал компьютер ZX Spectrum (Рис. 1), в своё время очень популярный в Советском Союзе). Рис. 1. Компьютер молодости нашей А задача такая. Подсчитать число разных прямоугольников в сетке 9 х 9 клеток (Рис. 2). 379
Рис. 2. Сетка из клеток Поскольку квадрат - это тоже прямоугольник, то самый первый квадратик уже можно посчитать (Рис. 3). Для уменьшения расхода бумаги мы дальше будем рассматривать сетку размером 3 х 3 клетки, а затем обобщим задачу. Рис. 3. Первый прямоугольник найден! Если мы будем расширять первый прямоугольник по ширине и высоте, то всего получим 9 прямоугольников (Рис. 4). Если мы переместим угловой квадрат на 1 и 2 строки ниже, а затем выполним те же «мероприятия», то насчитаем ещё 9 прямоугольников (Рис. 5). Точно так же мы подсчитаем прямоугольники для случая, когда единичный квадрат находится в первой и во второй колонках сетки (Рис. 6). Итого для сетки 3 х 3 мы насчитали 36 разных прямоугольников. Давайте разберёмся, как получилась эта сумма. 380
Рис. 4. Уменьшенная задача – 1 этап Рис. 5. Уменьшенная задача – 2 этап 381
Рис. 6. Уменьшенная задача – 3 этап 1. Мы передвигаем единичный квадрат от нулевой колонки до колонки 31 = 2 (не забывайте, что нумерация начинается с нуля!). На рисунках хорошо видно, что по ширине всегда получается 3-col прямоугольников. То есть: для col=0 → 3 для col=1 → 2 382
для col=2 → 1 2. Мы передвигаем единичный квадрат на всех колонках от нулевой строки и до строки 3-1=2. Каждый раз по высоте получается n-row прямоугольников. То есть: для row=0 → 3 для row=1 → 2 для row=2 → 1 3. Перемножаем число прямоугольников по ширине на число прямоугольников по высоте для всех значений col и row и добавляем к общей сумме. В итоге мы получаем число всех прямоугольников в сетке. И нам нужно только вместо размерности сетки 3 поставить число n – и задача решена! Итак, пользователь вводит число – размерность сетки. Она всегда квадратная, поэтому достаточно одного числа. Вы легко обобщите задачу для прямоугольных сеток, но тогда пользователь должен будет ввести два числа. Подсчёт прямоугольников мы произведём в функции calcRects (Рис. 7). Рис. 7 Функцию calcRects кодируем по нашему алгоритму (Рис. 8): 383
• Число прямоугольников мы храним в переменной res. • Изменяем номер колонки с единичным квадратиком от 0 до n-1. • Изменяем номер строки с единичным квадратиком от 0 до n-1. • Подсчитываем число новых прямоугольников для текущего значения col и row = 0..n-1. • Добавляем новые прямоугольники к общей сумме res: Рис. 8 Запускаем программу и находим число прямоугольников в любых квадратных сетках (Рис. 9). 384
Рис. 9. Прямоугольники сосчитаны Для задачи Синклера ответ такой: 2025 прямоугольников. На этом можно было бы и закончить решение задачи, но трудно не обратить внимания на то, что число прямоугольников всегда (по крайней мере, для наших значений сетки) равняется квадрату какого-либо числа: 1 – 12 9 – 32 36 – 62 100 – 102 225 – 152 441 – 212 784 – 282 1296 – 362 2025 – 452 3025 - 552 На сайте oeis.org эта же последовательность чисел скрывается под кодом A000537: 0, 1, 9, 36, 100, 225, 441, 784, 1296, 2025, 3025, 4356, 6084, 8281, 11025, 14400, 18496, 23409, 29241, 36100, 44100, 53361, 64009, 76176, 90000, 105625, 123201, 142884, 164836, 189225, 216225, 246016, 278784, 314721, 354025, 396900, 443556, 494209, 549081 385
И она не имеет никакого отношения к нашей задаче, а показывает сумму n первых кубов: 03 = 0 03+13 = 1 03+13+23=9 03+13+23+33=36 03+13+23+33+43=100 ... С другой стороны, последовательность 1, 3, 6, 10, 15, 21, 28, 36, 45, 55,… представляет собой треугольные числа. Треугольные числа – это разновидность фигурных чисел, о которых можно прочитать, например, в книге Мартина Гарднера Путешествие во времени (Рис. 10). Рис. 10. Фигурные числа Из Рис. 10 видно, что треугольные числа можно найти как сумму членов арифметической прогрессии: 1 + 2 + 3 + 4 + 5 + … = n(n+1)/2, 386
где n – номер треугольного числа. Решением задачи Клайва Синклера служат квадраты этих чисел, поэтому число прямоугольников в сетке размерами n x n клеток можно сразу же вычислить по формуле: (n(n+1)/2)2 Подставляем n = 9 и получаем ответ: (9х10/2)2 = 452 = 2025 Теперь сводим наши числовые наблюдения воедино и получаем забавную формулу, связывающую кубы и квадраты чисел (а также треугольные числа): 03 = 0 03+13 = (0 +1)2 = 1 03+13+23 = (0 +1 + 2)2 = 9 03+13+23+33 =(0 +1 + 2 + 3)2 = 36 03+13+23+33+43 = (0 +1 + 2 + 3 + 4)2 = 100 . . . Увы, не мы первые обнаружили это удивительное свойство степеней. Древнегреческий математик Никомах доказал теорему (Nicomachus's Theorem), согласно которой куб любого натурального числа можно представить в виде суммы последовательных нечётных чисел: 13 = 1 23 = 3 + 5 33 = 7 +9 + 11 43 = 13 + 15 + 17 + 19 . . . Из этой теоремы и вытекает то самое соотношение кубов и квадратов, которое мы вывели. Вот так, странным образом задача Клайва Синклера оказалась связана с древней теоремой Никомаха! 387
Задания для самостоятельного решения 1. Из Правил делимости чисел, которые мы рассмотрели в начале главы, легко вывести признаки делимости чисел на 15, 16, 18, 20, 22, 24, 25, 100, 1000. Попробуйте! 2. Докажите, что число, у которого число тысяч равно числу единиц, а число сотен равно числу десятков, делится на 11. 3. Докажите, что если двузначное число в 4 раза больше суммы цифр, то оно делится на 12. 4. Натуральное число называется полусовершенным, если оно равно сумме всех или некоторых своих делителей, исключая само число: 6, 12, 18, 20, 24, 28, 30, 36, 40. Например, 12 = 1 + 2 + 3 + 6 или 12 = 2 + 4 + 6. Из этого определения следует, что всякое совершенное число является и полусовершенным, то есть полусовершенных чисел в заданном диапазоне не меньше, чем совершенных. Напишите программу, которая находила бы несколько полусовершенных чисел. Вы ошиблись в подсчёте Удивительный мир чисел.. Задача 4 (2.2) ], страница 50 Ученик покупает 18 карандашей, 6 тетрадей, 12 ластиков, 9 блокнотов и несколько тетрадей для рисования по 15 к. Девушка-продавец выписала чек на 1 р. 52 к. Взглянув на чек, мальчик сразу же сказал продавцу: «Вы ошиблись в подсчёте». Девушка пересчитала и исправила свою ошибку. Как удалось пареньку так быстро обнаружить просчёт? Ответ: Стоимость каждой покупки, а значит и общая сумма кратна трём, но 1 р. 52 к. на три не делится. Задача #24 Математическая шкатулка Какое целое число делится (без остатка) на любое целое число, отличное от 0?. 388
Ответ: 0 Задача #25 Математическая шкатулка Сумма каких двух натуральных чисел равна их произведению? Ответ: 2 + 2 = 2 x 2- 389
Занятие_16. Черепашья графика https://project.edublocks.org/ATU8 Черепаха - русский Чарапаха - белорусский Tortoise, turtle - английский Galápago - испанский Testudo - латинский Tartaruga - португальский Впервые Черепашка появилась в языке программирования Лого (Logo), который был разработан в 1967 году Сеймуром Пейпертом и Идит Харель. Лого создавался как средство обучения детей дошкольного и младшего школьного возраста основам программирования. Главными объектами языка Лого были слова и предложения, что и определило выбор названия для самого языка – лого по-гречески значит слово. Но известность этому языку программирования принесла маленькая Черепашка (Turtle), которая умела выполнять несложные команды и вычерчивать линии. Именно благодаря Черепашке этот язык стал очень популярным в 70-80-е годы прошлого века, а Черепашка прижилась и в других языках программирования – LISP, SCHEME и многих версиях бейсика. Есть Черепашка и в Питоне - она «спрятана» в модуле turtle. В разных системах программирования Черепашки отличаются по форме. Обычно это стилизованные черепахи, но встречаются и примитивные виды Черепашек – равносторонние треугольники и наконечники стрелок (Рис. 1). Их объединяет желание ползать по экрану и возможность указывать направление их перемещения. Рис. 1. Черепашки разных видов 390
Морская черепашка По имени Наташка, С очками из Китая Такая вот крутая. Натали, Морская черепашка Каждый проект с Черепашкой должен начинаться с импорта модуля turtle (Рис. 1). Рис. 1 Все черепашьи блоки находятся на вкладке Turtle (Рис. 2). Рис. 2 Верхний блок – самый главный. Он создаёт Черепашку (Рис. 3). Рис. 3 Присоединяем его к проекту (Рис. 4). Рис. 4 391
Второй блок создаёт экран, или поверхность рисования (канву) для Черепашки (Рис. 5). Рис. 5 Следующий блок задаёт размеры поверхности рисования. По умолчанию Черепашка получает весь экран в своё распоряжение (Рис. 6). Рис. 6 Нам такой монументальный экран не нужен, поэтому задаём небольшие размеры (Рис. 7). Рис. 7 392
Запустите программу. Даже такой небольшой экран не помещается полностью в правой области Главного окна программы EduBlocks (Рис. 8). Рис. 8 Нажмите кнопку Popout (Рис. 9), чтобы черепаший экран появился в отдельном окне. Рис. 9 Размеры окна можно изменять, так что всю поверхность рисования хорошо видно. В центре поверхности рисования видна и Черепашка в образе чёрной стрелки, смотрящей вправо (Рис. 10). 393
Рис. 10 Но вы можете выбрать для Черепашки и другую форму: • • • • • • arrow turtle circle square triangle classic За форму Черепашки отвечает блок turtle.shape. По умолчанию функция shape получает пустую строку, и тогда Черепашка имеет форму стрелки (Рис. 11). Строка «arrow» превращает стрелку в треугольник (Рис. 12). Обратите внимание, что стрелка и треугольник смотрят вправо. Новорождённая Черепашка всегда появляется в центре канвы и смотрит вправо. 394
Рис. 11 Строка «turtle» создаёт почти настоящую Черепашку (Рис. 13). Рис. 12 Рис. 13 Дальше следуют простые геометрические фигуры (Рис. 14). Рис. 14 Классическая форма Черепашки – это стрелка по умолчанию (Рис. 15). 395
Рис. 15 По умолчанию Черепашка окрашена в чёрный цвет, но блок turtle.color позволяет задать любой цвет (Рис. 16). Рис. 16 Естественно, нам нужна Черепашка не для того, чтобы ей любоваться. Черепашка – это робот, который умеет выполнять наши команды. Команда turtle.forward посылает Черепашку вперёд на указанное расстояние в пикселях (Рис. 17). Рис. 17 «Вперёд» значит по направлению взгляда Черепашки. 396
Запустите программу. Черепашка ползёт вперёд и оставляет за собой след – отрезок прямой того же цвета, что и Черепашка (Рис. 18). Рис. 18 Это значит, что цвет Черепашки определяет и цвет линий. Толщину линий в пикселях задаёт блок turtle.width (Рис. 19 и 20). Рис. 19 397
Рис. 20 Скорость Черепашки можно изменить с помощью блока turtle.speed. Чем меньше значение скорости, тем медленнее перемещается Черепашка (Рис. 21). Рис. 21 Черепашка может ползти не только вперёд, но и пятиться назад (Рис. 22). Рис. 22 398
А также Черепашка умеет поворачиваться на заданный угол против часовой стрелки (Рис. 23) и по часовой стрелке (Рис. 24). Рис. 23 Рис. 24 Классы https://project.edublocks.org/8JRX Мы создали Черепашку, вызвав «функцию» Turtle (Рис. 1). Рис. 1 Но вы уже знаете, что имена функций принято писать со строчной буквы, а не с Прописной. В данном случае Turtle – это не функция, а имя класса. Вы и сами можете создавать классы. Для этого на вкладке Definitions найдите блок class (Рис. 2). Рис. 2 399
Перетащите его в область редактирования. Пусть наш класс называется Mashinka, потому что он будет просто печатать сообщения (Рис. 3). Рис. 3 Внутри класса мы можем создавать функции, которые также называют методами. Пусть функция print_message печатает полученное сообщение (Рис. 4). Рис. 4 Первым параметром метода должен быть параметр self. Он указывает, что метод принадлежит не классу, а объекту. Класс – это описание какого-либо объекта. По этому описанию мы должны создать экземпляр класса, или объект. Для этого нужно вызвать конструктор класса – имя класса и пару круглых скобок (Рис. 5). 400
Рис. 5 Мы создали объект с именем mash, и он получил от класса в полное своё распоряжение функцию print_message. Точно так же мы можем создать сколько угодно таких объектов (Рис. 6). Рис. 6 Каждый из этих объектов имеет функцию print_message. Но программа должна знать метод какого именно объекта нужно вызвать. Для этого сначала нужно указать имя объекта, потом поставить точку, а после точки 401
указать функцию, которую мы хотим вызвать. Аргументы, передаваемые в эти функции, могут быть разными. Запускаем программу и получаем 2 радостных сообщения от кота Матроскина (Рис. 7). Рис. 7 В EduBlocks очень мало блоков для работы с объектами, поэтому последние 2 блока «рукописные». Из этого следует, что создавать свои классы в EduBlocks смысла нет. Зато мы можем вовсю пользоваться готовыми классами Turtle и Screen. Создавать 2 поверхности рисования не нужно, а вот 2 Черепашки – вполне разумно. Пусть Черепашек зовут Миша и Маша (Рис. 8). Маша просто ползёт вперёд на 120 пикселей, Миша сначала поворачивается на 90 градусов против часовой стрелки, а затем ползёт вперёд на 120 пикселей. В итоге черепахоползания мы получаем вот такую замечательную картинку (Рис. 9). Теперь вы понимаете, что forward, backward, left, right – это функции, или методы объектов misha и masha. Чтобы указать полное имя метода, нужно написать имя объекта, поставить точку, а затем вызвать метод с нужным аргументом. 402
Рис. 8 Рис. 9 403
Этих знаний об объектно-ориентированном программировании вполне достаточно, чтобы успешно гонять Черепашек вдоль и поперёк! Цвет в компьютерной графике https://project.edublocks.org/tHtm Если вы хорошо знаете английские названия цветов, то можете использовать их в программах (Рис. 1 и 2). Рис. 1 С картинки название цвета не скопируешь, поэтому вот вам список цветов, сгруппированных по оттенкам. 404
Рис. 2 405
Red Colors IndianRed "#CD5C5C" LightCoral "#F08080" Salmon "#FA8072" DarkSalmon "#E9967A" LightSalmon "#FFA07A" Crimson "#DC143C" Red "#FF0000" FireBrick "#B22222" DarkRed "#8B0000" Pink Colors Pink "#FFC0CB" LightPink "#FFB6C1" HotPink "#FF69B4" DeepPink "#FF1493" MediumVioletRed "#C71585" PaleVioletRed "#DB7093" Orange-Yellow Colors LightSalmon "#FFA07A" Coral "#FF7F50" Tomato "#FF6347" OrangeRed "#FF4500" DarkOrange "#FF8C00" Orange "#FFA500" Gold "#FFD700" Yellow "#FFFF00" LightYellow "#FFFFE0" LemonChiffon "#FFFACD" LightGoldenrodYellow "#FAFAD2" PapayaWhip "#FFEFD5" Moccasin "#FFE4B5" PeachPuff "#FFDAB9" PaleGoldenrod "#EEE8AA" Khaki "#F0E68C" DarkKhaki "#BDB76B" Purple Colors Lavender "#E6E6FA" Thistle "#D8BFD8" Plum "#DDA0DD" Violet "#EE82EE" Orchid "#DA70D6" Fuchsia "#FF00FF" Magenta "#FF00FF" 406
MediumOrchid "#BA55D3" MediumPurple "#9370DB" BlueViolet "#8A2BE2" DarkViolet "#9400D3" DarkOrchid "#9932CC" DarkMagenta "#8B008B" Purple "#800080" Indigo "#4B0082" SlateBlue "#6A5ACD" DarkSlateBlue "#483D8B" MediumSlateBlue "#7B68EE" Green Colors GreenYellow "#ADFF2F" Chartreuse "#7FFF00" LawnGreen "#7CFC00" Lime "#00FF00" LimeGreen "#32CD32" PaleGreen "#98FB98" LightGreen "#90EE90" MediumSpringGreen "#00FA9A" SpringGreen "#00FF7F" MediumSeaGreen "#3CB371" SeaGreen "#2E8B57" ForestGreen "#228B22" Green "#008000" DarkGreen "#006400" YellowGreen "#9ACD32" OliveDrab "#6B8E23" Olive "#808000" DarkOliveGreen "#556B2F" MediumAquamarine "#66CDAA" DarkSeaGreen "#8FBC8F" LightSeaGreen "#20B2AA" DarkCyan "#008B8B" Teal "#008080" Blue Colors Aqua "#00FFFF" Cyan "#00FFFF" LightCyan "#E0FFFF" PaleTurquoise "#AFEEEE" Aquamarine "#7FFFD4" Turquoise "#40E0D0" MediumTurquoise "#48D1CC" 407
DarkTurquoise "#00CED1" CadetBlue "#5F9EA0" SteelBlue "#4682B4" LightSteelBlue "#B0C4DE" PowderBlue "#B0E0E6" LightBlue "#ADD8E6" SkyBlue "#87CEEB" LightSkyBlue "#87CEFA" DeepSkyBlue "#00BFFF" DodgerBlue "#1E90FF" CornflowerBlue "#6495ED" MediumSlateBlue "#7B68EE" RoyalBlue "#4169E1" Blue "#0000FF" MediumBlue "#0000CD" DarkBlue "#00008B" Navy "#000080" MidnightBlue "#191970" Brown Colors Cornsilk "#FFF8DC" BlanchedAlmond "#FFEBCD" Bisque "#FFE4C4" NavajoWhite "#FFDEAD" Wheat "#F5DEB3" BurlyWood "#DEB887" Tan "#D2B48C" RosyBrown "#BC8F8F" SandyBrown "#F4A460" Goldenrod "#DAA520" DarkGoldenrod "#B8860B" Peru "#CD853F" Chocolate "#D2691E" SaddleBrown "#8B4513" Sienna "#A0522D" Brown "#A52A2A" Maroon "#800000" White Colors White "#FFFFFF" Snow "#FFFAFA" Honeydew "#F0FFF0" MintCream "#F5FFFA" Azure "#F0FFFF" AliceBlue "#F0F8FF" 408
GhostWhite "#F8F8FF" WhiteSmoke "#F5F5F5" Seashell "#FFF5EE" Beige "#F5F5DC" OldLace "#FDF5E6" FloralWhite "#FFFAF0" Ivory "#FFFFF0" AntiqueWhite "#FAEBD7" Linen "#FAF0E6" LavenderBlush "#FFF0F5" MistyRose "#FFE4E1" Gray Colors Gainsboro "#DCDCDC" LightGray "#D3D3D3" Silver "#C0C0C0" DarkGray "#A9A9A9" Gray "#808080" DimGray "#696969" LightSlateGray "#778899" SlateGray "#708090" DarkSlateGray "#2F4F4F" Black "#000000" За цвет фона окна программы отвечает блок screen.bgcolour (Рис. 3). Рис. 3 Аргументом метода bgcolour может быть строка с названием цвета (Рис. 4). Рис. 4 409
Запускаем программу, и фон окна окрашивается в violetовый цвет (Рис. 5). Рис. 5 Вместо названия цвета вы можете использовать строку с 16-ричным числом. Результат вы получите тот же самый, но 16-ричные числа малопонятны (Рис. 6). Рис. 6 410
Глубина цвета Именованных цветов очень много! Но на экране монитора можно показать гораздо больше. Сколько? – А вот мы сейчас и подсчитаем! Каждый пиксель на экране занимает в памяти компьютера 32 бита памяти – по 8 битов (= 1 байту) на каждый цветной компонент (Рис. 1). Под компонентами понимают составляющие цвета: • • • • A(lpha) - прозрачность R(ed) - красная G(reen) - зелёная B(lue) - синяя Рис. 1. Пиксель Таким образом, глубина цвета - 32 бита. Обычно она и выражается числом битов на один пиксель (bits per pixel, bpp). Чем больше это значение, тем больше цветов можно показать на экране. Качество цветопередачи зависит также от установленной на компьютере видеокарты. Прозрачность не изменяет сам цвет, поэтому цвет пикселей на экране определяется значениями RGB-составляющих, а это 8 х 3 = 24 бита. Каждый бит может принимать 2 значения. Это значит, что всего мы можем получить 224 = 16 777 216 цветов, то есть почти 17 миллионов. Совершенно 411
понятно, что никто не сможет переименовать все эти миллионы цветов. Но тут на помощь языку приходит математика! Мы можем отдельно задать значения каждой составляющей цвета и передать эти значения в метод bgcolour. Оказывается, и так тоже можно! Для вывода изображений цветовая модель на экран обычно используется RGB (Red-Green-Blue, Красный-Зеленый- Синий), которая относится к аддитивным. Все цвета английское получаются слово добавлением addition значит (откуда и добавление, название: сложение) компонентов (первичных цветов) различной интенсивности к чёрному цвету. Все цвета, которые различает глаз человека, можно создать из этих трёх цветов, изменяя их интенсивность. При добавлении синего и красного цветов (полной интенсивности) мы получаем пурпурный, зелёного и красного – жёлтый, зелёного и синего – циановый. При смешивании всех цветов получается белый цвет. При отсутствии основных цветов мы получаем чёрный. Эта цветовая модель используется для формирования изображения на экранах телевизоров и мониторов, которые излучают свет. Проект Случайные цвета https://project.edublocks.org/rmJD Обычно значения цветовых составляющих задают целыми значениями в диапазоне 0..255, то есть каждая составляющая может принимать 256 разных значений. Все три составляющие дадут 256 х 256 х 256 = 16 777 216. Именно такое число цветов мы получили и раньше несколько другим способом. Итак, мы выяснили, что каждая цветовая составляющая может принимать значения от 0 до 255. Мы можем задавать цветовым составляющим слу412
чайные значения в бесконечном цикле while и наблюдать за изменениями цвета фона окна. Чтобы цвета не мелькали на экране, мы сделаем задержку в одну секунду. Для этого нам нужен блок time.sleep (Рис. 1). Рис. 1 Ему нужно передать время задержки в секундах (а не в миллисекундах, как в подсказке!). Чтобы пользоваться этим блоком, импортируйте модуль time. Остальные блоки программы в дальнейших комментариях не нуждаются (Рис. 2). Рис. 2 413
Запускаем программу и наблюдаем за сменой цветов (Рис. 3). Рис. 3 Проект Пунктир https://project.edublocks.org/WFDK В этом проекте мы научим Черепашку чертить зелёную пунктирную линию (Рис. 1). Рис. 1 414
Сначала и прежде всего мы создаём окно программы и Черепашку. Пусть линии будут зелёными толщиной 4 пикселя (Рис. 2). Рис. 2 Вы могли бы подумать, что Черепашка чертит линии хвостом, но это не так! У неё есть для этого инструмент – перо, или карандаш. Она может поднимать перо – блок turtle.penup – и опускать его – блок turtle.pendown (Рис. 3). В первом случае Черепашка просто перемещается по канве, не оставляя за собой след. Во втором случае она чертит линию. Рис. 3 Другой замечательный блок – turtle.goto(x, y) перемещает Черепашку в точку, заданную координатами (x, y) на канве (Рис. 4). Рис. 4 415
Начало координат находится в центре канвы. Положительное направление оси X – вправо, а оси Y – вверх (Рис. 5). Рис. 5 Если размеры канвы равны 480 x 320 пикселей, то горизонтальные координаты Черепашки изменяются от -240 до 240, а вертикальные – от -160 до 160. Давайте отправим Черепашку к левой границе окна (Рис. 6). И можно запускать процесс рисования! Переменная цикла i изменяется от 1 до 47. Если значение чётное, то Черепашка поднимает перо. Если нечётное – опускает его. После этого Черепашка ползёт вперёд на 10 пикселей (Рис. 7). 416
Рис. 6 Рис. 7 417
Полярная система координат Трутся об ось медведи,Вертится Земля… Песенка из комедии Кавказская пленница Кроме прямоугольной системы координат, которая известна всем и каждому, существуют и другие. Если вы хотите поставить точку на плоскости, вам нужны два числа. В декартовой системе координат это абсцисса и ордината, а в полярной - полярный радиус R и полярный угол Z. Полярный радиус называется также радиус-вектором. Длина радиус-вектора называется модулем. Начало полярных координат находится, как легко догадаться, в полюсе. Из него можно провести в любом направлении луч, образующий с полярной осью OL угол Z, который отсчитывается против часовой стрелки. Если луч проходит через заданную точку, то её положение в полярной системе координат определяется значениями полярного угла Z и полярного радиуса R, который равен расстоянию от точки до полюса. Очень хорошо это видно на картинке (Рис. 1). О – полюс OL – полярная ось ОА – луч, проходящий через заданную точку на плоскости R – полярный радиус точки Z – её полярный угол Рис. 1. Полярная система координат Поскольку координаты пикселей на экране удобнее задавать в прямоугольной системе координат, то давайте выведем формулы, по которым можно пересчитать координаты точки в полярной системе в координаты в прямоугольной системе. Для этого совместим начало прямоугольной системы координат с полюсом, а ось абсцисс – с полярной осью (Рис. 2). 418
Рис. 2. Координаты точки в двух системах координат Опустим перпендикуляры из точки Р на оси абсцисс и ординат. Точки пересечения перпендикуляров обозначим буквами x и y и рассмотрим прямоугольный треугольник OPx, из которого легко найдём координаты точки Р: x = R * cos(Z) y = R * sin(Z) (1) (2) Возникает вопрос: если от полярных координат так просто перейти к прямоугольным, то для чего вообще их использовать? – Дело в том, что в полярных координатах некоторые графические функции задавать гораздо проще, чем в прямоугольных. Например, окружности можно описать такими формулами: R = 1 – для единичной окружности или R = r – для окружности радиуса r Те же самые окружности в прямоугольных координатах имеют совсем непростой вид: x2 + y2 = 1 и x2 + y2 = r2 419
И многие другие кривые - спирали, улитки, розы, эллипсы, кардиоиды – удобнее задавать именно в полярных координатах. Чтобы убедиться в этом, давайте построим графики нескольких знаменитых кривых, описанных в полярных координатах. Проект Брейк https://project.edublocks.org/JVk6 Главное достоинство Черепашки в том, что она может передвигаться и в полярной системе координат. Действительно, при запуске программы Черепашка появляется в центре окна. Будем считать, что это полюс полярной системы координат. Два блока: поворачивают Черепашку вокруг собственной оси. Первый блок – произвольный угол в градусах против часовой стрелки, второй – по часовой стрелке. Например, мы легко заставим нашу Черепашку танцевать брейк (Рис. 1). С помощью этих блоков вы легко сможете переместить Черепашку в любую точку, заданную в полярных координатах. Например, выбрав полярный угол и полярный радиус (Рис. 2). 420
Рис. 1 Рис. 2 421
Проект Полярная Черепашка https://project.edublocks.org/Ut1E Всякий раз возвращая Черепашку в начало координат и поворачивая её на угол z, вы можете наставить сколько угодно точек в полярной системе координат. Например, вы можете расставить точки в вершинах правильного восьмиугольника (Рис. 1 и 2). Рис. 1 Рис. 2 422
Проект Полярная Черепашка 2 https://project.edublocks.org/sdMT А что получится, если продолжить передвижения Черепашки, не возвращая её в прежнее положение? – Тогда начало полярных координат переместится в точку, где находится Черепашка, а полярная ось повернётся по направлению взгляда Черепашки. Следующий поворот будет отсчитываться уже не от горизонтальной оси, а от нового положения полярной оси. Вы знаете, что все внутренние углы правильного треугольника равны 60 градусов, а внешние – 120, поэтому легко построите правильный треугольник (Рис. 1), если вычертите три его стороны, начиная каждую новую из конца предыдущей. Так как длина всех сторон одинакова, то достаточно повернуть Черепашку на нужный угол (Рис. 2). Рис. 1 Черепашка может рисовать и закрашенные фигуры (Рис. 3)! 423
Рис. 2 Рис. 3 424
Тогда блок turtle.pencolor задаёт цвет контура, а блок turtle.fillcolor – цвет заливки (Рис. 4). Рис. 4 Обратите внимание, что Черепашка подсказывает нам цвета контура и заливки. Блок turtle.begin_fill начинает процесс рисования фигуры с заливкой, а блок turtle.end_fill заканчивает его (Рис. 5). Рис. 5 Добавляем эти блоки в функцию triangle, чтобы нарисовать треугольник с заливкой (Рис. 6). Результат работы функции вы уже видели на Рис. 3⬆. Рис. 6 425
Проект Многоугольники https://project.edublocks.org/6svY Мы легко начертим любой правильный многоугольник, но нам вполне достаточно двух – шести- и восьмиугольника. Начнём с младшего многоугольного братца. В функции polygon6 важно отправить Черепашку в нужное место канвы для начала рисования, а также выбрать длину сторон шестиугольника. Затем в цикле for Черепашка поворачивается на 60 градусов (360 : 6 = 60) в каждой итерации и ползёт вперёд на r пикселей (Рис. 1). Рис. 1 В оставшейся части программы мы создаём окно и Черепашку, после чего смело вызываем функцию polygon6 (Рис. 2). 426
Рис. 2 Запускаем программу. Черепашка поработала, как пчёлка, и вычертила замечательный шестиугольник (Рис. 3). Рис. 3 427
Давайте поможем Черепашке заполнить сот мёдом (Рис. 4). Рис. 4 Получилось красиво и сладко (Рис. 5)! Восьмиугольник мёдом заполнять не нужно, поэтому чертим его без особых прикрас (Рис. 6). 428
Рис. 5 Рис. 6 429
Для построения любого правильного многоугольника нам потребовалось написать всего несколько строк кода и при этом – никаких расчётов координат вершин! Нетрудно догадаться, что если задать достаточно большое число вершин, то многоугольник превратится в окружность (Рис. 7). Рис. 7 На вкладке Turtle есть специальный блок turtle.circle, который чертит окружность заданного радиуса (Рис. 8). Рис. 8 430
На Рис. 9 окружность, вычерченная эти блоком, зелёного цвета. Рис. 9 Если на каждой итерации немного увеличивать радиус, то вместо окружности получится замечательная спираль (Рис. 10). → Блок turtle.left закручивает спираль против часовой стрелки (Рис. 11). Блок turtle.right закручивает спираль по часовой стрелке (Рис. 12). 431
Рис. 11 Рис. 12 432
Блок turtle.speed задаёт скорость перемещения Черепашки (Рис. 13). Чем быстрее двигается Черепашка, тем ровнее получаются линии. Проект Черепашьи загогулины https://project.edublocks.org/kmc9 А теперь давайте перейдём к более сложным кривым, которые наверняка убедят вас в том, что вы не напрасно познакомились с Черепашкой. Для начала мы заставим многоугольники вращаться вокруг одной из своих вершин (Рис. 1 и 2). 433
Рис. 1 Рис. 2 А так Черепашка вычертит вращающиеся шестиугольники (Рис. 3 и 4). 434
Рис. 3 Рис. 4 435
Проект Рекурсивная Черепашка https://project.edublocks.org/aEhn Необыкновенно простая рекурсивная функция polySpi при разных параметрах даёт потрясающее многообразие великолепных спиралей (Рис. 14)! Рис. 1 436
Рис. 2 Рис. 3 437
Рис. 4 Квадратная спираль с закруткой (Рис. 5-6). Рис. 5 438
Рис. 6 Треугольная спираль (Рис. 7-8). Рис. 7 439
Рис. 8 Треугольная спираль с закруткой (Рис. 9-10). Рис. 9 440
Рис. 10 Многоугольная спираль (Рис. 11-12). Рис. 11 441
Рис. 12 442
Проект Звёздчатая Черепашка https://project.edublocks.org/vgAi И последний проект на этом занятии – вычерчивание разнообразных звёздчатых многоугольников (Рис. 1-2). Рис. 1 443
Рис. 2 Число зубцов определяется значением параметра n (Рис. 3-4). Рис. 3 444
Рис. 4 445
Литература [Нагибин88] Нагибин Ф.Ф., Канин Е.С. Математическая шкатулка М.: Просвещение, 1988. – 160 с. [ОО80] Оре О. Приглашение в теорию чисел М.: Наука, 1980 г. - 128 с. Библиотечка Квант, Выпуск 3 446
[КА86] [КА96] Б.А. Кордемский, А.А.Ахадов Удивительный мир чисел (МАТЕМАТИЧЕСКИЕ ГОЛОВОЛОМКИ И ЗАДАЧИ ДЛЯ ЛЮБОЗНАТЕЛЬНЫХ) М.: Просвещение, 1986. – 144 с. М.: Просвещение, 1996. – 159 с 447
[ЗП88] Абрамов С.А. и др. Задачи по программированию Наука, 1988. – 224 с. ISBN: 5-02-013774-Х Серия: Библиотечка программиста [100] В. А. Дагене, Г. К. Григас, К. Ф. Аугутис 100 задач по программированию М.:Просвещение, 1993. – 251 с. ISBN: 5-09-003864-3 448
[ВНН88] Воробьёв Н.Н. Признаки делимости Наука. - 1988, 96 с. ISBN 5-02-013731-6 [БК85] Брудно А. Л. Каплан Л. И. Олимпиады по программированию для школьников Наука. - 1985, 96 с. 449
[BE13] Ehrhard Behrends Fünf Minuten Mathematik: 100 Beiträge der Mathematik-Kolumne der Zeitung DIE WELT Springer Spektrum. - 2013, 272 с. 3-е издание ISBN: 978-3-658-00998-4 [ГМ72] Гарднер Мартин Математические досуги М.: Мир, 1972. – 495 с. 450
[ЛВ88] Липский В. Комбинаторика для программистов Москва: Мир, 1988. – 200 с. [РВ11] Рубанцев Валерий Delphi в примерах, играх и программах. От простых приложений, решения задач и до программирования интеллектуальных игр Наука и Техника, 2011. – 672 с. ISBN: 978-5-94387-664-6 Серия: Самоучитель 451