Сравнение и логика
Кроме подсчётов, калькулятор Swift отвечает на вопросы «да или нет». Больше ли одно число другого? Совпадают ли две строки? Ответ — значение типа Bool: true или false. Такие ответы понадобятся, как только программа начнёт выбирать, что делать дальше.
Шесть операторов сравнения
Оператор сравнения берёт два значения и возвращает Bool:
==— равно;!=— не равно;<и>— меньше и больше;<=и>=— меньше или равно, больше или равно.
let age = 17
print(age >= 18) // false
print(age == 17, age != 17) // true false
let isAdult = age >= 18
print(isAdult) // falseРазберём по строкам:
age >= 18спрашивает, исполнилось ли 18. Ответfalse.age == 17даётtrue, аage != 17—false.- Результат сравнения можно положить в константу: в
isAdultлежитfalse.
Один знак = кладёт значение в константу или переменную, а два знака == сравнивают. Имя для Bool обычно читается как утверждение: isAdult, hasTicket.
Логические операторы
Представьте охранника на входе в клуб. Он пропускает гостя с билетом, если тому есть 18. Гостя из списка VIP пропускают и без билета. Чтобы записать такие правила, условия объединяют логическими операторами.
let hasTicket = true
let isVip = false
print(isAdult && hasTicket) // false
print(isVip || hasTicket) // true
print(!isVip) // trueИ: &&
a && b даёт true, только когда верны обе части. Билет у гостя есть, но ему 17, поэтому isAdult && hasTicket — это false.
ИЛИ: ||
a || b даёт true, когда верна хотя бы одна часть. Гость не из списка VIP, но билет у него есть, поэтому isVip || hasTicket — это true.
НЕ: !
!a меняет ответ на противоположный. isVip равно false, значит, !isVip — это true.
Правая часть может не вычисляться
Охранник, увидев, что гостю нет 18, билет уже не спрашивает: ответ «нет» и так известен. Swift поступает так же. Если левая часть && равна false, правая не вычисляется вовсе. У || наоборот: при true слева правую часть Swift пропускает. Это называют вычислением по короткой схеме.
Короткая схема защищает от деления на ноль. Деление целого числа на ноль во время работы аварийно завершает программу, а проверка слева от && не даёт ему выполниться:
let total = 10
let count = 0
let isBig = count > 0 && total / count > 2
print(isBig) // falsecount > 0— этоfalse, ведьcountравен нулю.- Ответ
&&уже известен, иtotal / countне вычисляется. - Программа печатает
falseи не завершается аварийно.
Здесь картинка с охранником неточна: живой охранник может спросить билет и у того, кого уже не пустил. Swift в таком случае правую часть не вычисляет никогда, и на этом держится защита от деления на ноль.
Вычисление по короткой схеме часто встречается на собеседовании. Обычно спрашивают, выполнится ли правая часть &&, если левая равна false.
Сравнение строк
Строки тоже сравнивают. Оператор == проверяет, что строки совпадают символ в символ. Операторы < и > сравнивают строки слева направо по номерам символов: у каждого символа в компьютере есть свой номер. Меньше та строка, у которой первый несовпавший символ имеет меньший номер. Для строчных латинских букв это совпадает с порядком в словаре, а в других случаях — не всегда:
"кот" == "Кот"— этоfalse: заглавная и строчная буквы разные."apple" < "banana"— этоtrue: первая букваaстоит раньшеb."Zebra" < "apple"— тожеtrue: у заглавнойZномер меньше, чем у строчнойa."10" < "9"— этоtrue: строки сравниваются не как числа, а по символам, и у1номер меньше, чем у9."ёж" < "жук"— этоfalse: у буквыёномер больше, чем уж, и даже больше, чем уя.
Частая ошибка
Проверку на ноль поставили справа от деления:
let total = 10
let count = 0
let isBig = total / count > 2 && count > 0 // ✗
print(isBig)Fatal error: Division by zeroЛевая часть && вычисляется первой, и деление на ноль аварийно завершает программу ещё до проверки. Проверка, которая защищает действие, должна стоять слева от &&.
Главное
- Операторы
==,!=,<,>,<=и>=сравнивают два значения и даютBool. &&даётtrue, только когда верны обе части,||— когда верна хотя бы одна, а!меняет ответ на противоположный.- Если ответ ясен по левой части
&&или||, правая часть не вычисляется. - Строки сравниваются по символам:
"Zebra" < "apple"и"10" < "9"— этоtrue.