Кроме арифметических операций со школы нам известны операции сравнения. Например, 5 > 4
. Это звучит как вопрос: «5 больше 4?». В данном случае ответ «да». В других случаях ответом может быть «нет» (например, для 3 < 1
).
Операции сравнения не имеют привязки к числам. Сравнивать можно практически всё, что угодно, например, строки. Каждый раз, когда мы входим на какой-то сайт, внутри происходит сравнение введенных логина и пароля с теми, какие есть в базе. И только если они есть, нас пускают во внутрь (аутентифицируют).
Языки программирования адаптировали все математические операции сравнения практически в неизменном виде. Единственное серьезное отличие – операторы равенства и неравенства. В математике для этого используется обычное равно =
, но в программировании такое встречается не часто. Во многих языках символ =
используется для присваивания значений переменным, поэтому для сравнения взяли ==
или ===
.
Список операций сравнения:
<
меньше<=
меньше или равно>
больше>=
больше или равно===
равно!==
не равноДля равенства и неравенства также существуют операторы ==
и !=
, которые мы не будем использовать из-за потенциальной опасности. Мы поговорим об этом ниже.
Логическая операция типа 5 > 4
или $password === $text
— это выражение, и его результат — специальное значение true
(«истина») или false
(«ложь»). Это новый для нас тип данных — bool. Он содержит всего лишь два этих значения. Наряду со строками (string) и целыми и рациональными числами, тип bool (булев) — это один из примитивных типов данных в PHP.
<?php
$result = 5 > 4;
print_r($result); // => true
print_r('one' !== 'one'); // => false
Напишем примитивную функцию, которая принимает на вход возраст ребенка и определяет, младенец ли он. Младенцами считаются дети до года:
Пользуемся тем фактом, что любая операция — это выражение, поэтому единственной строчкой функции пишем «вернуть то значение, которое получится в результате сравнения $age < 1
».
В зависимости от пришедшего аргумента сравнение будет либо истинным (true
), либо ложным (false
), а return
вернёт этот результат.
<?php
function isInfant($age)
{
return $age < 1;
}
// Для вывода bool используем var_dump(), а не print_r()
var_dump(isInfant(3)); // => bool(false)
var_dump(isInfant(0.5)); // => bool(true)
Подобные функции называют предикатами. Функции-предикаты (или функции-вопросы) отвечают на какой-то вопрос и всегда (без исключений!) возвращают либо true
, либо false
.
Предикаты во всех языках принято именовать особым образом для простоты анализа. В PHP предикаты, как правило, начинаются с префикса is
, has
или can
, но не ограничены этими словами. Примеры:
isInfant()
— «младенец ли?»hasChildren()
— «есть ли дети?»isEmpty()
— «пустой ли?»hasErrors()
— «есть ли ошибки?»Логические операции — это выражения. Значит, логические операции можно комбинировать с другими выражениями. Например, мы хотим проверить чётность числа, то есть кратность двум. В программировании используют такой подход:
Остаток от деления — простая, но очень важная концепция в арифметике, алгебре, и даже в теории чисел и криптографии. Идея проста: нужно разделить число на несколько равных групп, и если в конце что-то останется — это и есть остаток от деления.
Делим конфеты поровну между людьми:
Оператор %
вычисляет остаток от деления (не путайте с делением):
7 % 2
→ 1
21 % 3
→ 0
19 % 5
→ 4
С помощью него напишем функцию проверки чётности:
<?php
function isEven($number)
{
return $number % 2 === 0;
}
isEven(10); // true
isEven(3); // false
В одном выражении мы скомбинировали логический оператор ===
(проверка равенства) и арифметический оператор %
. Приоритет арифметических операций выше логических. Значит, сначала вычисляется арифметическое выражение $number % 2
, затем результат участвует в логическом сравнении. По-русски это можно расшифровать так: «вычислить остаток от деления числа $number
на 2 и сравнить, равен ли остаток нулю; затем вернуть результат проверки равенства».
Логические выражения могут объединяться друг с другом, создавая всё более хитрые проверки. Хороший пример: проверка пароля. Как вы знаете, некоторые сайты при регистрации хотят пароль от 8 до 20 символов в длину. Честно говоря, это странное ограничение, но что поделать. В математике мы бы написали 8 < x < 20
(где x
это длина конкретного пароля), но в PHP такой трюк не пройдет. Нам придётся сделать два отдельных логических выражения и соединить их специальным оператором «И»:
<?php
function hasSpecialChars($str)
{
// проверяет содержание специальных символов в строке
}
// функция принимает пароль и проверяет, соответствует ли он условиям
function isCorrectPassword($password)
{
$length = strlen($password);
// Скобки задают приоритет. Понятно что к чему относится.
return ($length > 8 && $length < 20) || hasSpecialChars($password);
}
isCorrectPassword('qwerty'); // false
isCorrectPassword('qwerty1234'); // true
isCorrectPassword('zxcvbnmasdfghjkqwertyui'); // false
&&
- означает «И» (в математической логике это называют конъюнкцией). Всё выражение считается истинным только в том случае, когда истинен каждый операнд — каждое из составных выражений. Иными словами, &&
означает «и то, и другое». Приоритет этого оператора ниже, чем приоритет операторов сравнения, поэтому выражение отрабатывает правильно без скобок. Кроме &&
, часто используется оператор ||
— «ИЛИ» (дизъюнкция). Он означает «или то, или другое, или оба». Операторы можно комбинировать в любом количестве и любой последовательности, но когда одновременно встречаются &&
и ||
, то приоритет лучше задавать скобками.
Область математики, в которой изучаются логические операторы, называется булевой алгеброй. Ниже показаны «таблицы истинности» — по ним можно определить, каким будет результат применения оператора:
&&
A | B | A && B |
---|---|---|
TRUE | TRUE | TRUE |
TRUE | FALSE | FALSE |
FALSE | TRUE | FALSE |
FALSE | FALSE | FALSE |
||
A | B | A ‖ B |
---|---|---|
TRUE | TRUE | TRUE |
TRUE | FALSE | TRUE |
FALSE | TRUE | TRUE |
FALSE | FALSE | FALSE |
Наряду с конъюнкцией (И) и дизъюнкцией (ИЛИ), часто используется операция «отрицание». Отрицание меняет логическое значение на противоположное. В программировании ему соответствует унарный оператор !
. Если есть функция, проверяющая чётность числа, то с помощью отрицания можно выполнить проверку нечётности:
<?php
function isEven($number)
{
return $number % 2 === 0;
}
isEven(10); // true
!isEven(10); // false
// В логике двойное отрицание подобно отсутствию отрицания вообще
!!isEven(10); // true
То есть мы просто добавили !
слева от вызова функции и получили обратное действие. Отрицание — мощный инструмент, который позволяет лаконично выражать задуманные правила в коде без необходимости писать новые функции.
Напомним, что PHP — это язык со слабой типизацией. Он знает о существовании разных типов (числа, строки и др.), но относится к их использованию не очень строго, пытаясь преобразовывать информацию, когда это кажется разумным. Особенно много автоматических преобразований происходит при работе с логическими операциями. В PHP есть два простых правила, по которым происходят преобразования:
0
, ''
(пустая строка), null
приводятся к false
. Эти значения называют falsy.true
.Это работает и в другую сторону: true
и false
преобразовываются в другие типы данных, в зависимости от ситуации:
<?php
print_r(true); // => 1
print_r(false); // => (на экран выводится пустая строка)
print_r(0 || 1); // => 1
Оператор ИЛИ работает только с типом bool, но ему даны числа 1
и 0
.
0
преобразуется в false
, а 1
преобразуется в true
.false || true
— это true
.print_r()
получает true
, но он работает только со строками (не с bool).true
преобразуется в 1
.1
.Здесь важно отметить также отличие операторов ==
и !=
. Оно как раз заключается в преобразовании типов. Пустая строка и false
— это разные значения, поэтому оператор ===
говорит «ложь! они не равны!». Но оператор ==
преобразует типы, и с его точки зрения пустая строка и false
равны. Это преобразование неявное, поэтому по возможности избегайте операторов ==
и !=
.
<?php
var_dump('' === false); // => false
var_dump('' == false); // => true
Вспомним операцию отрицания. При двойном отрицании !!
итоговое значение равно начальному:
<?php
$answer = true;
var_dump(!$answer); // => false
var_dump(!!$answer); // => true
Здесь также дополнительно происходят преобразования типа. Поэтому результатом двойного отрицания всегда будет bool. Этим приёмом пользуются, чтобы поменять тип данных.
В разных языках программирования разные правила преобразований. Некоторые языки вообще не преобразовывают типы сами. Многие особенности PHP откровенно не самые удачные, но это историческое наследие языка. Если бы его создавали сегодня с нуля, то многие правила и нюансы наверняка были бы совсем иными.
Вам ответят команда поддержки Хекслета или другие студенты.
Выделите текст, нажмите ctrl + enter и отправьте его нам. В течение нескольких дней мы исправим ошибку или улучшим формулировку.
Загляните в раздел «Обсуждение»:
Курсы программирования для новичков и опытных разработчиков. Начните обучение бесплатно.
Наши выпускники работают в компаниях:
С нуля до разработчика. Возвращаем деньги, если не удалось найти работу.
Зарегистрируйтесь или войдите в свой аккаунт
Задавайте вопросы, если хотите обсудить теорию или упражнения. Команда поддержки Хекслета и опытные участники сообщества помогут найти ответы и решить задачу