Множество значений логического типа logical
содержит всего два элемента - true
(истина) и false
(ложь). Эти константы определены так, что true
равняется 1
, false
равняется 0
и true > false
.
Значения логического типа обычно получаются в результате сравнения с использованием следующих операторов:
==
: равенство. Например,a == b
возвращает1
, еслиa
равноb
.~=
: неравенство. Например,x ~= y
возвращает1
, еслиx
не равноy
.<
: меньше. Например,p < q
возвращает1
, еслиp
меньшеq
.>
: больше. Например,m > n
возвращает1
, еслиm
большеn
.<=
: меньше или равно. Например,r <= s
возвращает1
, еслиr
меньше или равноs
.>=
: больше или равно. Например,t >= u
возвращает1
, еслиt
больше или равноu
.
class(3 < 4)
ans =
'logical'
Сравнение значений полезно в исследовании математических выражений, анализе данных (фильтрации по условию) и в построении управляющих конструкций.
Кроме операторов сравнения для построения логических выражений используются логические операторы:
~
- отрицание&&
- логическое И||
- логическое ИЛИ
Например, x > 0 && x < 10
истинно только в том случае, если x
больше 0
и одновременно меньше 10
. Обычно мы бы сказали, что x
находится между 0
и 10
, не включая конечные значения.
x = 5;
disp(x > 0 && x < 10);
x = -1;
disp(x > 0 && x < 10);
x = 11;
disp(x > 0 && x < 10);
1
0
0
mod(n, 2) == 0 || mod(n, 3) == 0
истинно, если выполняется хотя бы одно из условий, то есть если число делится на 2 или на 3. В этом случае одна или другая часть (или обе) должны быть истинными, чтобы результат был истинным.
n = 1;
disp(mod(n, 2) == 0 || mod(n, 3) == 0);
n = 2;
disp(mod(n, 2) == 0 || mod(n, 3) == 0);
n = 3;
disp(mod(n, 2) == 0 || mod(n, 3) == 0);
n = 2 * 3;
disp(mod(n, 2) == 0 || mod(n, 3) == 0);
0
1
1
1
Наконец, оператор отрицания ~
инвертирует булево выражение, поэтому ~ x > y
будет истинным, если x > y
ложно, то есть если x
меньше или равно y
.
x = -1;
y = 1;
disp(~(x > y));
1
Приведем таблицы результатов этих логических операций для всех возможных значений операндов (в алгебре логики такие такие таблицы называются таблицами истинности).
x |
~x |
---|---|
1 | 0 |
0 | 1 |
x |
y |
x && y |
x || y |
---|---|---|---|
0 | 0 | 0 | 0 |
0 | 1 | 0 | 1 |
1 | 0 | 0 | 1 |
1 | 1 | 1 | 1 |
Замечание. Часто допускают ошибки при написании булевых выражений. Например, запись number == 5 || 6 || 7
в MATLAB некорректна, так как оператор ||
должен соединять булевы выражения. Правильный вариант: (number == 5) || (number == 6) || (number == 7)
. Хотя это кажется громоздким, это необходимо; нельзя использовать сокращения. Аналогично, выражение a < b < c
интерпретируется как (a < b) < c
. Чтобы проверить a < b < c
математически, следует писать (a < b) && (b < c)
.
В логических выражениях могут встречаться как арифметические операции, так и логические. Порядок выполнения операций определяется их приоритетом (в других языках программирования приоритеты операций могут быть другими):
- Скобки
()
- Отрицание
~
- Умножение
*
и деление/
- Сложение
+
и вычитание-
- Операторы сравнения: меньше
<
, нестрогое меньше<=
, больше>
, нестрогое больше>=
, равенство==
, не равно~=
- Логические И
&&
- Логическое ИЛИ
||
Операции с одинаковым приоритетом выполняются по порядку слева направо. Для изменения порядка необходимо воспользоваться кргулыми скобками ()
.
При вычислении булевских выражений их значение может стать известным еще до конца вычисления всего выражения. Например:
h_plus = 10e-8; % молярная концентрация H+
% Вычисление кислотности раствора PH
is_water = (h_plus > 0) && (6.5 <= -log10(h_plus) && -log10(h_plus) <= 8.5)
В случае, если бы h_plus = 0
, уже после первого операнда операции &&
ясно, что результат всего выражения - ложь 0
(false
), поэтому второй операнд вычисляться не будет. Если бы первый операнд отсутсвовал, то формула была бы ошибочна при неккоректном входном аргументе h_plus
.
Нередко при составлении программ со сложными логическими выражениями, необходимо строить их отрицания (см. “На тему вложенности кода”). Для этого полезно воспользоваться следующими тождествами:
~~a
\(\equiv\)a
~(a && b)
\(\equiv\)(~a) || (~b)
~(a || b)
\(\equiv\)(~a) && (~b)
Последние два тождества известны как законы де Моргана.
Следует иметь ввиду отрицания операторов отношения:
Оператор | Определение | Логические противоположности |
---|---|---|
== |
Равно | ~= |
~= |
Не равно | == |
< |
Меньше | >= |
<= |
Меньше или равно | > |
> |
Больше | <= |
>= |
Больше или равно | < |
Понимание логических противоположностей позволяет нам иногда избавляться от операторов отрицания ~
. Они часто усложняют чтение кода, и без них наши намерения становятся яснее.
Например, если бы мы написали следующий код на MATLAB:
if ~(age >= 17)
disp("Вы слишком молоды, чтобы получить водительские права!")
end
Следовало бы упростить и написать вместо этого:
if age < 17
disp("Вы слишком молоды, чтобы получить водительские права!")
end
Законы де Моргана также могут облегчить понимание условий. Рассмотрим пример:
if ~((phone_charge >= 0.50) && (phone_storage >= 0.15))
disp("Вы не можете обновить телефон. Низкий заряд батареи или недостаточно свободного места.")
else
disp("Идет обновление... Может потребоваться несколько перезагрузок.")
end
После преобразования:
if (phone_charge < 0.50) || (phone_storage < 0.15)
disp("Вы не можете обновить телефон. Низкий заряд батареи или недостаточно свободного места.")
else
disp("Идет обновление... Может потребоваться несколько перезагрузок.")
end
Вместо применения законов Де Моргана, можно было избавиться от оператора отрицания ~
, поменяв местами логические части «тогда» и «иначе» в условии:
if (phone_charge >= 0.50) && (phone_storage >= 0.15)
disp("Идет обновление... Может потребоваться несколько перезагрузок.")
else
disp("Вы не можете обновить телефон. Низкий заряд батареи или недостаточно свободного места.")
end
Последняя версия, вероятно, лучшая из трех, потому что она очень точно соответствует первоначальному логическому утверждению.
В программировании почти всегда существует несколько способов решить любую задачу. Хорошие программы спроектированы, делая выбор в пользу ясности, простоты и изящности.