Урок №46. Логічні оператори: І, АБО, НЕ

  Юрій  | 

  Оновл. 2 Тра 2020  | 

 377

У той час як оператори порівняння використовуються для перевірки конкретної умови: помилкова вона чи істинна, вони можуть перевірити тільки одну умову за певний проміжок часу. Але бувають ситуації, коли потрібно протестувати відразу декілька умов. Наприклад, щоб дізнатися, чи виграли ми в лотерею, нам потрібно порівняти всі цифри купленого квитка з виграшними. Якщо в лотереї 6 цифр, то потрібно виконати 6 порівнянь, всі з яких мають бути true.

Також іноді нам потрібно знати, чи є хоч одне з декількох умов істинним. Наприклад, ми не підемо сьогодні на роботу, якщо хворі або дуже втомилися, або якщо виграли в лотерею 🙂 Нам потрібно перевірити, чи є хоч одна з цих 3-х умов істинною. Як це зробити? За допомогою логічних операторів! Вони дозволяють перевірити відразу декілька умов за раз.

У C++ є 3 логічних оператори:

Оператор Символ Приклад Операція
Логічне НЕ ! !x true, якщо x — false і false, якщо x — true
Логічне І && x && y true, якщо x і y — true, в протилежному випадку — false
Логічне АБО || x || y true, якщо x чи y — true, в протилежному випадку — false

Логічний оператор НЕ

Ми вже з ним стикалися в уроці про логічний тип даних bool.

Логічний оператор НЕ (!)
Операнд Результат
true false
false true

Якщо операндом є true, то після застосування логічного НЕ результатом стане false. Якщо ж операнд до застосування оператора НЕ є false, то після його застосування — стане true. Іншими словами, логічний оператор НЕ змінює результат з true на false і навпаки. Він часто використовується в умовних виразах:

Слід пам’ятати, що логічний оператор НЕ має дуже високий рівень пріоритету. Початківці часто роблять наступну помилку:

Результат виконання програми:

х equals у

Але х не дорівнює у, як це можливо? Оскільки пріоритет логічного оператора НЕ вище, ніж пріоритет оператора рівності, то вираз !х==у обчислюється як (!х)==у. Так як х — це 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 не застосовується короткий цикл обчислення. Однак його легко можна зімітувати, використовуючи оператор нерівності (!=):

Можна також збільшити кількість операндів:

Слід зазначити, що наведені вище шаблони XOR працюють тільки, якщо операнди є логічного типу даних (а не цілочисельних типів). Якщо ви хочете, щоб це працювало і з цілими числами, то використовуйте оператор static_cast.

Форма XOR, яка працює і з іншими типами даних (за допомогою static_cast ми можемо конвертувати будь-який тип даних в bool):

Тест

Який результат виконання наступних виразів?

   (true && true) || false

   (false && true) || true

   (false && true) || false || true

   (5 > 6 || 4 > 3) && (7 > 8)

   !(7 > 6 || 3 > 4)

Відповідь

Примітка: У відповідях пояснення виконується за допомогою стрілочки (=>). Наприклад, (true || false) => true означає, що результатом виразу (true || false) є true.

   (true && true) || false => true || false => true

   (false && true) || true => false || true => true

   (false && true) || false || true => false || false || true => false || true => true

   (5 > 6 || 4 > 3) && (7 > 8) => (false || true) && false => true && false => false

   !(7 > 6 || 3 > 4) => !(true || false) => !true => false

Оцінити статтю:

1 Зірка2 Зірки3 Зірки4 Зірки5 Зірок (1 оцінок, середня: 5,00 з 5)
Loading...

Залишити відповідь

Ваш E-mail не буде опублікований. Обов'язкові поля відмічені *