Урок №43. Логические операторы: И, ИЛИ, НЕ
На этом уроке мы рассмотрим логические операторы И, ИЛИ и НЕ в языке С++.
Логические операторы
В то время как операторы сравнения используются для проверки конкретного условия: ложное оно или истинное, они могут проверить только одно условие за определенный промежуток времени. Но бывают ситуации, когда нужно протестировать сразу несколько условий. Например, чтобы узнать, выиграли ли мы в лотерею, нам нужно сравнить все цифры купленного билета с выигрышными. Если в лотерее 6 цифр, то нужно выполнить 6 сравнений, все из которых должны быть true.
Также иногда нам нужно знать, является ли хоть одно из нескольких условий истинным. Например, мы не пойдем сегодня на работу, если больны или слишком устали, или если выиграли в лотерею. Нам нужно проверить, является ли хоть одно из этих трех условий истинным. Как это сделать? С помощью логических операторов! Они позволяют проверить сразу несколько условий за раз.
В языке C++ есть 3 логических оператора:
Оператор | Символ | Пример | Операция |
Логическое НЕ | ! | !x | true, если x — false и false, если x — true |
Логическое И | && | x && y | true, если x и y — true, в противном случае — false |
Логическое ИЛИ | || | x || y | true, если x или y — true, в противном случае — false |
Логический оператор НЕ
Мы уже с ним сталкивались на уроке №34.
Логический оператор НЕ (!) | |
Операнд | Результат |
true | false |
false | true |
Если операндом является true, то, после применения логического НЕ, результатом будет false. Если же операнд до применения оператора НЕ был false, то после его применения станет true. Другими словами, логический оператор НЕ меняет результат на противоположный начальному значению. Он часто используется в условных выражениях:
Следует помнить, что логический оператор НЕ имеет очень высокий уровень приоритета. Новички часто совершают следующую ошибку:
Результат выполнения программы:
Но х ведь не равно у , как это возможно? Поскольку приоритет логического оператора НЕ выше, чем приоритет оператора равенства, то выражение ! х == у обрабатывается как (! х) == у . Так как х — это 5 , то !x — это 0 . Условие 0 == у ложное, поэтому выполняется часть else!
Напоминание: Любое ненулевое целое значение в логическом контексте является true. Так как х = 5 , то х вычисляется как true, а вот !x = false , т.е. 0 . Использование целых чисел в логических операциях подобным образом может запутать не только пользователя, но и самого разработчика, поэтому так не рекомендуется делать!
Правильный способ написания программы, приведенной выше:
Сначала обрабатывается х == у , а затем уже оператор НЕ изменяет результат на противоположный.
Правило: Если логический оператор НЕ должен работать с результатами работы других операторов, то другие операторы и их операнды должны находиться в круглых скобках.
Логический оператор ИЛИ
Если хоть одно из двух условий является истинным, то логический оператор ИЛИ является true.
Логический оператор ИЛИ (||) | ||
Левый операнд | Правый операнд | Результат |
false | false | false |
false | true | true |
true | false | true |
true | true | true |
Рассмотрим следующую программу:
Здесь мы использовали логический оператор ИЛИ, чтобы проверить, является ли хоть одно из двух условий истинным: левое ( value == 0 ) или правое ( value == 1 ). Если хоть одно из условий — true или оба сразу true, то выполняться будет стейтмент if. Если ни одно из условий не является true, то результат — false и выполняться будет стейтмент else.
Вы можете связать сразу несколько условий:
Новички иногда путают логическое ИЛИ ( || ) с побитовым ИЛИ ( | ). Хоть у них и одинаковые названия, функции они выполняют разные.
Логический оператор И
Только при условии, что оба операнда будут истинными, логический оператор И будет true. Если нет, тогда — false.
Логический оператор И (&&) | ||
Левый операнд | Правый операнд | Результат |
false | false | false |
false | true | false |
true | false | false |
true | true | true |
Например, мы хотим узнать, находится ли значение переменной х в диапазоне от 10 до 20. Здесь у нас есть два условия: мы должны проверить, является ли х больше 10 и является ли х меньше 20.
Если оба условия истинны, то выполняется часть if. Если же хоть одно или сразу оба условия ложные, то выполняется часть else.
Как и с логическим ИЛИ, мы можем комбинировать сразу несколько условий И:
Короткий цикл вычислений
Для того, чтобы логическое И возвращало true, оба операнда должны быть истинными. Если первый операнд вычисляется как false, то оператор И должен сразу возвращать false независимо от результата второго операнда (даже без его обработки). Это называется коротким циклом вычисления (англ. «short circuit evaluation») и выполняется он, в первую очередь, в целях оптимизации.
Аналогично, если первый операнд логического ИЛИ является true, то и всё условие будет true (даже без обработки второго операнда).
Как и в случае с оператором ИЛИ, новички иногда путают логическое И ( && ) с побитовым И ( & ).
Использование логических операторов И/ИЛИ
Иногда возникают ситуации, когда смешивания логических операторов И и ИЛИ в одном выражении не избежать. Тогда следует знать о возможных проблемах, которые могут произойти.
Многие программисты думают, что логические И и ИЛИ имеют одинаковый приоритет (или забывают, что это не так), так же как и сложение/вычитание или умножение/деление. Тем не менее, приоритет логического И выше приоритета ИЛИ. Таким образом, операции с оператором И всегда будут вычисляться первыми (если только операции с ИЛИ не находятся в круглых скобках).
Рассмотрим следующее выражение: value1 || value2 && value3 . Поскольку приоритет логического И выше, то обрабатываться выражение будет так:
value1 || (value2 && value3)
(value1 || value2) && value3
Хорошей практикой является использование круглых скобок с операциями. Это предотвратит ошибки приоритета, увеличит читабельность кода и чётко даст понять компилятору, как следует обрабатывать выражения. Например, вместо того, чтобы писать value1 && value2 || value3 && value4 , лучше записать (value1 && value2) || (value3 && value4) .
Законы Де Моргана
Многие программисты совершают ошибку, думая, что !(x && y) — это то же самое, что и !x && !y . К сожалению, вы не можете использовать логическое НЕ подобным образом.
Законы Де Моргана гласят, что !(x && y) эквивалентно !x || !y , а !(x || y) эквивалентно !x && !y .
Другими словами, логические операторы И и ИЛИ меняются местами! В некоторых случаях, это даже полезно, так как улучшает читабельность.
А где же побитовое исключающее ИЛИ (XOR)?
Побитовое исключающее ИЛИ (XOR) — это логический оператор, который используется в некоторых языках программирования для проверки на истинность нечётного количества условий.
Побитовое исключающее ИЛИ (XOR) | ||
Левый операнд | Правый операнд | Результат |
false | false | false |
false | true | true |
true | false | true |
true | true | false |
В языке C++ нет такого оператора. В отличии от логических И/ИЛИ, к XOR не применяется короткий цикл вычислений. Однако его легко можно сымитировать, используя оператор неравенства ( != ):
Логические операторы в си
Л огические операторы – это операторы, которые принимают в качестве аргументов логические значений (ложь или истину) и возвращают логическое значение. Как и обычные операторы, они могут быть одноместными (унарными, т.е. принимать один аргумент), двуместными (бинарные, принимают два аргумента), трёхместными и т.д.
Особенностью языка си является то, что в нём нет типа, хранящего булево значение (ложь или истину). В си ложью (логическим нулём) считается целочисленный 0, а любое ненулевое целое будет логической истиной. Например
Логические значения обычно порождаются операторами сравнения (==, !=, >, <, >=. <=).
В языке си представлено три логических оператора: И, ИЛИ и НЕ. Начнём с самого простого
Логическое отрицание
О ператор НЕ (NOT) используется для того, чтобы инвертировать значение аргумента. Т.е., если ему передали истину, то он вернёт ложь, если получил ложь в качестве аргумента, то вернёт истину.
X | NOT X |
---|---|
0 | 1 |
1 | 0 |
В си отрицание представлено оператором !. Например
Как и в обычной логике, здесь действует закон двойного отрицания – отрицание отрицания можно опустить.
Логическое И
О ператор И (AND, логическое умножение) возвращает истину тогда и только тогда, когда оба аргумента являются истиной.
X | Y | X AND Y |
---|---|---|
0 | 0 | 0 |
0 | 1 | 0 |
1 | 0 | 0 |
1 | 1 | 1 |
В си логическое умножение представлено оператором &&. Например, задача – в кружок военных спейсмаринов допускаются только совершеннолетние граждане мужского пола. То есть, претендентом может стать только тот, для которого одновременно два условия являются истиной
Оператор И может применяться последовательно к нескольким аргументам. Для него действует ассоциативный и коммутативный законы. Усовершенствуем программу, будем также вводить рост:
Также условие могло быть записано
Логическое ИЛИ
О ператор логическое ИЛИ (логическое сложение, OR) истинен тогда, когда истиной является хотя бы один его аргумент.
X | Y | X OR Y |
---|---|---|
0 | 0 | 0 |
0 | 1 | 1 |
1 | 0 | 1 |
1 | 1 | 1 |
В си ИЛИ представлен оператором ||. Например, усовершенствуем программу: теперь пол можно вводить как большой, так и маленькой буквой
Как и в случае оператора И, ИЛИ коммутативен и ассоциативен.
Операторы можно перемешивать друг с другом, создавая сложные операторы
Стоит только помнить о том, что оператор отрицания имеет больший приоритет, чем И или ИЛИ, поэтому будет выполняться в первую очередь. Если может случиться ситуация, когда порядок выполнения не ясен, определите его с помощью скобок.
Пример: закон де-Моргана. Чтобы сменить И на ИЛИ (или наоборот), необходимо инвертировать значения всех операндов, заменить И на ИЛИ (или ИЛИ на И) и инвертировать конечный результат. В случае с нашим условием
Рассмотрим сначала кусок
Меняем все значения на обратные
заменяем оператор && на ||
и инвертируем ответ
Как видим, результат тот же. Очевидно, что
Таким образом, изменим условие
Поменяем таким же образом вторую скобку
Теперь можно применить это же правило и для всего выражения
Порядок выполнения логических операторов
Р ассмотрим выражение
где a, b, c, d – логические значения. Всё выражение равно истине тогда и только тогда, когда все операнды истинны. Если хотя бы один из операндов ложь, то остальные уже не важны. Поэтому, для оптимизации работы, вычисление происходит слева направо и останавливается, как только был найден первый операнд, равный нулю.
В си оператор присваивания может возвращать значение. Иногда он используется непосредственно в условии:
В данном случае, оператор malloc не будет выполнен, так как первый операнд a равен 0 (соответственно, всё выражение равно нулю). Таким образом, оператор free попытается очистить память, которую не может очистить (т.к. p продолжит ссылаться на a). Если же мы поменяем a = 1, то всё отработает без проблем.
То же самое происходит и при выполнение ||. Выражение
выполняется слева направо до тех пор, пока не встретит первое ненулевое значение. После этого выполнение останавливается, так как известно, что всё выражение равно истине.
Очевидно, что это касается не только оператора присваивания, но и любого другого вызова функции. Например, в этом случае функции foo будет вызвана, bar нет.
Вывод – не используйте присваивания и вызовов функций (особенно, если они изменяют состояние программы) внутри условий.
Всё ещё не понятно? – пиши вопросы на ящик
Операции в языке Си
Над объектами в языке Си могут выполняться различные операции:
- операции присваивания;
- операции отношения;
- арифметические;
- логические;
- сдвиговые операции.
Результатом выполнения операции является число.
Операции могут быть бинарными или унарными.
Бинарные операции выполняются над двумя объектами, унарные — над одним.
Операция присваивания
Операция присваивания обозначается символом = и выполняется в 2 этапа:
- вычисляется выражение в правой части;
- результат присваивается операнду, стоящему в левой части:
объект = выражение;
В случае если объекты в левой и правой части операции присваивания имеют разные типы используется операция явного приведения типа.
объект = (тип)выражение;
Операции отношения
Основные операции отношения:
- == эквивалентно — проверка на равенство;
- != не равно — проверка на неравенство;
- < меньше;
- > больше;
- <= меньше или равно;
- >= больше или равно.
Операции отношения используются при организации условий и ветвлений. Результатом этих операций является 1 бит, значение которого равно 1 , если результат выполнения операции — истина, и равно 0 , если результат выполнения операции — ложь.
Арифметические операции
Основные бинарные операции, расположенные в порядке уменьшения приоритета:
- * — умножение;
- / — деление;
- + — сложение;
- — — вычитание;
- % — остаток от целочисленного деления.
Основные унарные операции:
- ++ — инкрементирование (увеличение на 1);
- –– — декрементирование (уменьшение на 1);
- — — изменение знака.
Результат вычисления выражения, содержащего операции инкрементирования или декрементирования, зависит от того, где расположен знак операции (до объекта или после него). Если операция расположена до объекта, то сначала происходит изменение значения переменной на 1, а потом это значение используется для выполнения следующих операций. Если операция ++ или — расположена после переменной, то сначала выполняется операция, а потом значение переменной изменяется на 1.
Бинарные арифметические операции могут быть объединены с операцией присваивания:
- объект *= выражение; // объект = объект * выражение
- объект /= выражение; // объект = объект / выражение
- объект += выражение; // объект = объект + выражение
- объект -= выражение; // объект = объект — выражение
- объект %= выражение; // объект = объект % выражение
Логические операции
Логические операции делятся на две группы:
- условные;
- побитовые.
Условные логические операции чаще всего используются в операциях проверки условия if и могут выполняться над любыми объектами. Результат условной логической операции:
- 1 если выражение истинно;
- 0 если выражение ложно.
Вообще, все значения, отличные от нуля, интерпретируются условными логическими операциями как истинные.
Основные условные логические операции:
- && — И (бинарная) — требуется одновременное выполнение всех операций отношения;
- || — ИЛИ (бинарная) — требуется выполнение хотя бы одной операции отношения;
- ! — НЕ (унарная) — требуется невыполнение операции отношения.
Побитовые логические операции оперируют с битами, каждый из которых может принимать только два значения: 0 или 1.
Основные побитовые логические операции в языке Си:
- & конъюнкция (логическое И) — бинарная операция, результат которой равен 1 только когда оба операнда единичны (в общем случае — когда все операнды единичны);
- | дизъюнкция (логическое ИЛИ) — бинарная операция, результат которой равен 1 когда хотя бы один из операндов равен 1;
Для каждого бита результат выполнения операции будет получен в соответствии с таблицей.
a; // e = 241 = 1111 0001
f = a ^ b; // f = 7 = 0000 0111
Побитовые операции позволяют осуществлять установку и сброс отдельных битов числа. С этой целью используется маскирование битов . Маски, соответствующие установке каждого бита в байте, представлены в таблице
Бит | Маска |
0 | 0x01 |
1 | 0x02 |
2 | 0x04 |
3 | 0x08 |
4 | 0x10 |
5 | 0x20 |
6 | 0x40 |
7 | 0x80 |
Для установки определенного бита необходимо соответствующий бит маски установить в 1 и произвести операцию побитового логического ИЛИ с константой, представляющей собой маску:
Для сброса определенного бита необходимо соответствующий бит маски сбросить в 0 и произвести операцию побитового логического И с константой, представляющей собой инверсную маску:
0x02); // a = 1, бит 1 сброшен
Бинарные побитовые логические операции могут быть объединены с операцией присваивания:
- объект &= выражение; // объект = объект & выражение
- объект |= выражение; // объект = объект | выражение
- объект ^= выражение; // объект = объект ^ выражение
Сдвиговые операции
Операции арифметического сдвига применяются в целочисленной арифметике и обозначаются как:
- >> — сдвиг вправо;
- << — сдвиг влево.
Общий синтаксис осуществления операции сдвига:
объект = выражение сдвиг КоличествоРазрядов;
Арифметический сдвиг целого числа вправо >> на 1 разряд соответствует делению числа на 2.
Арифметический сдвиг целого числа влево << на 1 разряд соответствует умножению числа на 2.
Логические операторы: И, ИЛИ, РАВНО и другие
Логические операторы это специальные символы (или сочетания символов), которые изменяют или комбинируют логические значения типа Boolean — true и false. Их используют чтобы создавать сложные условия, например в циклах.
Логические операторы
Оператор НЕ (!, not)
Выражение вида !true равно false и наоборот. ! — унарный оператор (применяется к одному операнду), он помещается перед операндом.
Оператор И (&&, and)
Выражение вида a && b будет равно true только тогда, когда и а и b равны true.
Оператор ИЛИ (||, or)
Выражение a || b будет равно true, когда или a, или b (или оба) равен true.
Оператор исключающее ИЛИ (^, xor)
Выражение a ^ b будет равно true, когда только один из операндов имеет значение true. Подробно о применении xor рассказывается в статье « Практика применения XOR в программировании »
Оператор эквивалентности ==
Выражение a == b будет равно true, когда a и b имеют одинаковые значения.
Оператор неравенства !=
Выражение a != b будет равно true, когда a и b имеют разные значения.
Приоритет логических операторов
- Оператор эквивалентности — ==, оператор неравенства — !=.
- Оператор отрицания — !.
- Оператор И — &&.
- Оператор исключающее ИЛИ — ^.
- Оператор ИЛИ — ||.
Предлагаем вам пройти тест и узнать, насколько хорошо вы разобрались с логическими операторами:
Ссылка на резюме
Для отправки формы требуется ваше согласие
Спасибо за участие! Нам потребуется немного времени, чтобы обработать все ответы. Свяжемся с тобой в ближайшее время. А пока можешь посмотреть наш Youtube-канал и ближе познакомиться с нашим 1С направлением. Или почитать наш блог на habr.