ВУЗ: Не указан
Категория: Не указан
Дисциплина: Не указана
Добавлен: 04.12.2023
Просмотров: 129
Скачиваний: 1
ВНИМАНИЕ! Если данный файл нарушает Ваши авторские права, то обязательно сообщите нам.
15
Таблица 2
Логические выражения
Знак сравнения
Описание
< меньше
> больше
<= меньше либо равно
>= больше либо равно
== равно
!= не равно
В Питоне допустимы и логические выражения, содержащие несколько знаков сравнения, например x < y < z. При этом все сравнения обладают одинаковым приоритетом, который меньше, чем у любой арифметической операции.
Результат вычисления логического выражения можно сохранять в переменную, которая будет иметь тип bool. Переменные такого типа, как и числа, и строки, являются неизменяемыми объектами.
Строки также могут сравниваться между собой. При этом сравнение происходит в лексикографическом порядке (как упорядочены слова в словаре).
Логические операции
Чтобы записать сложное логическое выражение, часто бывает необходимо воспользоваться логическими связками «и», «или» и «не». В
Питоне они обозначаются как and, or и not соответственно. Операции and и or являются бинарными, т. е. должны быть записаны между операндами, например x < 3 or y > 2. Операция not – унарная и должна быть записана перед единственным своим операндом.
Все логические операции имеют приоритет ниже, чем операции сравнения (а значит, ниже, чем арифметические операции). Среди
16 логических операций наивысший приоритет имеет операция not, затем идет and, наименьший приоритет имеет операция or. На порядок выполнения операций можно влиять с помощью скобок, как и в арифметических выражениях.
Примеры использования логических выражений
Одним из примеров использования логического выражения является проверка на делимость. Например, чтобы проверить, является ли число четным, необходимо сравнить остаток от деления этого числа на два с нулём
(рис. 22).
Рис. 22. Пример использования логических выражений
Рассмотрим задачу о пересечении двух длительных по времени событий. Оба события характеризуются двумя числами – годами их начала и окончания. Необходимо определить, пересекались ли события во времени.
При этом если одно событие началось в тот год, когда закончилось другое, они считаются пересекающимися.
Первая идея заключается в том, чтобы рассмотреть все возможные варианты расположения событий и выделить следующий критерий пересечения: если начало или конец одного из событий лежит между началом и концом другого, то они пересекаются. В виде программы это можно записать так, как представлено на рис. 23.
17
Рис. 23. Пример использования логических выражений
Если немного подумать, то можно придумать более короткий критерий для проверки такого пересечения: необходимо, чтобы начало первого события происходило не позже конца второго и начало второго события происходило не позже конца первого (рис. 24).
Рис. 24. Пример использования логических выражений
Такой способ значительно проще.
Условный оператор
Наиболее частое применение логические выражения находят в условных операторах.
Условный оператор позволяет выполнять действия в зависимости от того, выполнено условие или нет. Записывается условный оператор как "
if
<логическое выражение>:
''
. Далее следует блок команд, который будет выполнен, только если логическое выражение приняло значение True. Блок команд, который будет выполняться, выделяется отступами в 4 пробела (в
IDE можно нажимать клавишу tab).
18
Рассмотрим, например, задачу о нахождении модуля числа. Если число отрицательное, то необходимо заменить его на минус это число. Решение выглядит так, как представлено на рис. 25.
Рис. 25. Использование логического оператора
В этой программе с отступом записана только одна строка, x = –x. При необходимости выполнить несколько команд все они должны быть записаны с тем же отступом. Команда print записана без отступа, поэтому она будет выполняться в любом случае, независимо от того, было ли условие в if'е истинным или нет.
В дополнение к if можно использовать оператор else: (иначе). Блок команд, который следует после него, будет выполняться, если условие было ложным. Например, ту же задачу о выводе модуля числа можно было решить, не меняя значения переменной x (рис. 26).
Рис. 26. Использование логического оператора
Все команды, которые выполняются в блоке else, должны быть также записаны с отступом. Else должен следовать сразу за блоком команд if, без промежуточных команд, выполняемых безусловно.
Else без соответствующего if'а не имеет смысла.
19
Если после if записано не логическое выражение, то оно будет приведено к логическому, как если бы от него была вызвана функция bool.
Однако злоупотреблять этим не следует, т. к. это ухудшает читаемость кода.
Для подсчета модуля числа в Питоне существует функция abs, которая избавляет от необходимости каждый раз писать подсчет модуля вручную.
В Питоне, как и во многих других языках программирования, если результат вычисления выражения однозначно понятен по уже вычисленной части, то оставшаяся часть выражения даже не считается. Например, выражение True or 5 // 0 == 42 не будет вызывать ошибки деления на ноль, т. к. по левой части выражения (True) уже понятно, что результат его вычисления также будет True и арифметическое выражение в правой части даже не будет вычисляться.
Вложенный условный оператор и конструкция «иначе – если»
Вложенный условный оператор
Внутри блока команд могут находиться другие условные операторы.
Посмотрим на примере. По заданному количеству глаз и ног нужно научиться отличать кошку, паука, морского гребешка и жучка. У морского гребешка бывает более сотни глаз, а у большинства пауков их восемь
. Также у пауков восемь ног, а у морского гребешка их нет совсем. У кошки четыре лапы, а у жучка – шесть ног, но глаз у обоих по два. Решение представлено на рис. 27.
20
Рис. 27. Использование вложенного условного оператора
Если вложенных условных операторов несколько, то к какому из них относится else, можно понять по отступу. Отступ у else должен быть такой же, как у if, к которому он относится.
Конструкция «иначе – если»
В некоторых ситуациях необходимо осуществить выбор больше чем из двух вариантов, которые могут быть обработаны с помощью if-else.
Рассмотрим пример: необходимо вывести словом название числа 1 или 2 или сообщить, что это другое число (рис. 28).
Рис. 28. Использование конструкции if-else
Здесь используется специальная конструкция elif, обозначающая
«иначе, если», после которой записывается условие. Такая конструкция введена в язык Питон, потому что запись if-else приведет к увеличению отступа и ухудшению читаемости.
Конструкций elif может быть несколько, условия проверяются последовательно.
Как только условие выполнено, запускается соответствующий этому условию блок команд и дальнейшая проверка не выполняется. Блок else является необязательным, как и в обычном if.
Цикл while
21
While переводится как «пока» и позволяет выполнять команды до тех пор, пока условие верно. После окончания выполнения блока команд, относящихся к while, управление возвращается на строку с условием, и если оно выполнено, то выполнение блока команд повторяется, а если не выполнено, то продолжается выполнение команд, записанных после while.
С помощью while очень легко организовать вечный цикл, поэтому необходимо следить за тем, чтобы в блоке команд происходили изменения, которые приведут к тому, что в какой-то момент условие перестанет быть истинным.
Рассмотрим несколько примеров.
Есть число N. Необходимо вывести все числа по возрастанию от 1 до
N. Для решения этой задачи нужно завести счётчик (переменную i), который будет равен текущему числу. Вначале это единица. Пока значение счетчика не превысит N, необходимо выводить его текущее значение и каждый раз увеличивать его на единицу (рис. 29).
Рис. 29. Использование цикла while
Еще одна часто встречающаяся задача – поиск минимума (или максимума) в последовательности чисел. Пусть задана последовательность чисел, оканчивающаяся нулём. Необходимо найти минимальное число в этой последовательности. Эта задача может быть решена человеком в уме: каждый раз, когда ему называют очередное число, он сравнивает его с текущим запомненным минимумом и, при необходимости, запоминает новое минимальное число. В качестве первого запомненного числа нужно взять
22 первый элемент последовательности, который должен быть считан отдельно до цикла (рис. 30).
Рис. 30. Использование цикла while
Инструкция для прерывания цикла называется break. После её выполнения работа цикла прекращается (как будто не было выполнено условие цикла). Осмысленное использование конструкции break возможно, только если выполнено какое-то условие, то есть break должен вызываться только внутри if (находящегося внутри цикла). Использование break – плохой тон, по возможности следует обходиться без него. Рассмотрим пример вечного цикла, выход из которого осуществляется с помощью break. Для этого решим задачу о выводе всех целых чисел от 1 до 100. Использовать break таким образом ни в коем случае не нужно, это просто пример (рис. 31).
Рис. 31. Использование цикла while
В языке Питон к циклу while можно написать блок else. Команды в этом блоке будут выполняться, если цикл завершил свою работу нормальным образом (т. е. условие в какой-то момент перестало быть истинным), и не
23 будут выполняться только в случае, если выход из цикла произошел с помощью команды break.
Подсчет суммы и оператор continue
Часто возникает задача о подсчете суммы последовательности. Для подсчета суммы чисел необходимо завести переменную, которая будет хранить накопленную на данный момент сумму и, при чтении очередного числа, прибавлять его к накопленной сумме (рис. 32).
Рис. 32. Использование цикла while
Команда continue начинает исполнение тела цикла заново, начиная с проверки условия. Её нужно использовать, если начиная с какого-то места в теле цикла и при выполнении каких-то условий дальнейшие действия нежелательны.
Приведём пример использования continue (хотя при решении этой задачи можно и нужно обходиться без него): дана последовательность чисел, оканчивающаяся нулём. Необходимо вывести все положительные числа из этой последовательности. Решение представлено на рис. 33.
Рис. 33. Пример использования continue
24
В этом решении есть интересный момент: перед циклом переменная инициализируется заведомо подходящим значением. Команда вывода будет выполняться только в том случае, если не выполнится условие в if.
1.3. Работа с данными, содержащими с вещественные числа
Как устроены вещественные числа
В отличие от целых чисел, вещественные числа в языке Питон имеют ограниченную длину.
Подумаем, как хранить десятичную дробь в памяти. Поскольку вещественных чисел бесконечно много (даже больше, чем натуральных), то нам придется ограничить точность. Например, мы можем хранить только несколько первых значащих цифр, не храня незначащие нули. Будем отдельно хранить целое число с первыми значащими цифрами и отдельно хранить степень числа 10, на которую нужно умножить это число.
Например, число 5.972*
10**24 (
это масса Земли в килограммах) можно сохранить как 5972 (цифры числа, мантисса) и
21
(на какую степень 10 нужно умножить число, экспонента). С помощью такого представления можно хранить вещественные числа любой размерности.
Примерно так и хранятся числа в памяти компьютера, однако вместо десятичной системы используется двоичная. На большинстве аппаратных систем в языке Питон для хранения float используется 64 бита, из которых 1 бит уходит на знак, 52 бита – на мантиссу и 11 бит – на экспоненту.
Это упрощенное описание
, но достаточно неплохо описывает реальность.
52 бита дают около 15–16 десятичных знаков, которые будут храниться точно. 11 бит на экспоненту также накладывает ограничения на размерность хранимых чисел (примерно от
–1000 до 1000 степени числа 10).
Любое вещественное число на языке Питон представимо в виде дроби, где в числителе хранится целое число, а в знаменателе находится какая-либо
25 степень двойки. Например, 0.125 представимо как 1/8, а 0.1 как
3602879701896397/36028797018963968. Несложно заметить, что эта дробь не равна 0.1, т. е. хранение числа 0.1 точно в типе float невозможно, как и многих других «красивых» десятичных дробей.
В целом будет полезно представлять себе вещественное число X как отрезок [X – epsilon; X + epsilon]. Как же определить величину epsilon?
Для этого нужно понять, что погрешность не является абсолютной, т. е. одинаковой для всех чисел, а является относительной. Упрощенно аппаратную погрешность хранения числа X можно оценить как X*2**(–54).
Чаще всего в задачах входные данные имеют определенную точность.
Рассмотрим на примере. Заданы два числа X и Y с точностью 6 знаков после точки (значит, epsilon=5*10**(–7)), по модулю не превосходящие 10**9.
Оценить абсолютную погрешность вычисления X * Y. Рассмотрим худший случай, когда X и Y равны 10**9 и отклонились на максимально возможное значение epsilon в одну сторону. Тогда результат вычисления будет выглядеть так:
(X + epsilon) * (Y + epsilon) = XY + (X + Y) * epsilon + epsilon**2.
Величина epsilon**2 пренебрежимо мала, XY – это правильный ответ, а
(X + Y) * epsilon – искомое значение абсолютной погрешности. Подставим числа и получим:
2 * 10**9 * 5 * 10**(–7) = 10**3.
Абсолютная погрешность вычисления составила 1000 (одну тысячу).
Что довольно неожиданно и грустно.
Таким образом, нужно аккуратно вычислять значение погрешности для сравнения вещественных чисел.
Основы работы с вещественными числами
Для записи констант или при вводе-выводе может использоваться как привычное представление в виде десятичной дроби, например: 123.456, так и
«инженерная» запись числа, где мантисса записывается в виде
26 вещественного числа с одной цифрой до точки и некоторым количеством цифр после точки, затем следуют буква «e» (или «E») и экспонента. Число
123.456 в инженерной записи будет выглядеть так: 1.23456e2. Это означает, что 1.23456 нужно умножить на 10**2. И мантисса, и экспонента могут быть отрицательными и записываются в десятичной системе.
Такая запись чисел может применяться при создании вещественных констант, а также при вводе и выводе. Инженерная запись удобна для хранения очень больших или очень маленьких чисел, чтобы не считать количество нулей в начале или конце числа.
Если хочется вывести число не в инженерной записи, а с фиксированным количеством знаков после точки, то следует воспользоваться методом format, который имеет массу возможностей. Нам нужен только вывод фиксированного количества знаков, поэтому воспользуемся готовым рецептом для вывода 25 знаков после десятичной точки у числа 0.1 (рис. 34).
Рис. 34. Использование метода format
Вывод такой программы будет выглядеть как
0.1000000000000000055511151, что еще раз подтверждает мысль о том, что число 0.1 невозможно сохранить точно.
Проблемы вещественных чисел
Рассмотрим простой пример с вещественными числами (рис. 35).
Рис. 35. Пример с вещественными числами