Логічні оператори проти побітових операторів


75

Мене бентежить, коли слід використовувати булеві та побітові оператори

  • and проти &
  • or проти |

Чи міг хтось просвітити мене щодо того, коли я використовую кожен і коли використання одного над іншим вплине на мої результати?


14
Зауважте, що відповіді, які ви отримаєте, приблизно стосуються всіх інших (загальнообов’язкових) мов.

Відповіді:


77

Ось кілька рекомендацій:

  • Логічні оператори зазвичай використовуються для булевих значень, але побітові оператори зазвичай використовуються для цілих значень.
  • Логічні оператори мають коротке замикання, але побітові оператори не замикають.

Поведінка короткого замикання корисна у таких виразах:

if x is not None and x.foo == 42:
    # ...

Це не буде коректно працювати з побітовим &оператором, оскільки обидві сторони завжди оцінюватимуться, даючи AttributeError: 'NoneType' object has no attribute 'foo'. Коли ви використовуєте логічний andоператор, другий вираз не обчислюється, коли перший - False. Подібним orчином не оцінює другий аргумент, якщо перший є True.


13
Додатково: В Python &, |, ^встановлені операції теж.
kennytm

5
Додаткові додаткові відомості: у Python побітовий режим не допускає змішаних типів, але логічний. наприклад, True or "True"це нормально (він поверне перше неправдиве значення), але True | "True"видасть виняток.
Hannele

8
@Hannele Це не має нічого спільного зі змішаними типами. Побітові операції мають сенс лише з цілими числами, і будь-який інший тип видасть виняток. Справа в тому, що Python обробляє False та True як 0 та 1 відповідно: 0 == Falseі 1 == Trueобидва вони є true.
Нуно Андре

1
@ NunoAndré Досить правда, це більш точне пояснення. Дякую!
Ганнеле

24

Теоретично, andі orвиходити прямо з логічної логіки (і, отже, оперувати двома логічними значеннями для створення логічного значення), &і |застосовувати логічне значення та / або до окремих бітів цілих чисел. Тут є багато питань щодо того, як саме працюють останні.

Ось практичні відмінності, які потенційно можуть вплинути на ваші результати:

  1. andі orкоротке замикання, наприклад True or sys.exit(1), не вийде, оскільки для певного значення першого операнда ( True or ..., False and ...) другий не змінить результат, тому не потрібно обчислювати. Але |і &не замикайте коротке замикання - True | sys.exit(1)викидає вас за межі REPL.
  2. &і |регулярні оператори і може бути перевантажено, в той час як andі orвикувані на мову (хоча спеціальний метод для примусу до булеву може мати побічні ефекти).
    • Це також стосується деяких інших мов із перевантаженням оператора
  3. andі orповернути значення операнда замість Trueабо False. Це не змінює значення булевих виразів в умовах - 1 or Trueце 1, але 1це правда, теж. Але колись він використовувався для емуляції умовного оператора ( cond ? true_val : false_valу синтаксисі С, true_val if cond else false_valу Python). Для &і |тип результату залежить від того, як операнди перевантажують відповідні спеціальні методи ( True & Falseце False, 99 & 7є 3, для наборів це об'єднання / перетин ...).
    • Це також стосується деяких інших мов, таких як Ruby, Perl та Javascript

Але навіть тоді , коли , наприклад , a_boolean & another_booleanбуде працювати однаково, правильне рішення використовує and- просто тому , що andі orпов'язане з логічним виразом і станом в той час &і |стояти з битами.


21

Ось ще одна різниця, яка мене просто здивувала деякий час: оскільки &(та інші побітові оператори) мають вищий пріоритет, ніж and(та інші логічні оператори), наступні вирази оцінюються в різні значення:

0 < 1 & 0 < 2

проти

0 < 1 and 0 < 2

До речі, перший поступається, Falseоскільки він еквівалентний 0 < (1 & 0) < 2, отже 0 < 0 < 2, отже 0 < 0 and 0 < 2.


4

Якщо ви намагаєтесь виконати елементарні логічні операції в numpy, відповідь дещо інша. Ви можете використовувати &і |для елементальних булевих операцій, але andі orповерне значення помилки.

Щоб бути в безпеці, ви можете використовувати функції логіки numpy .

np.array([True, False, True]) | np.array([True, False, False])
# array([ True, False,  True], dtype=bool)

np.array([True, False, True]) or np.array([True, False, False])
# ValueError: The truth value of an array with more than one element is ambiguous. Use a.any() or a.all()

np.logical_or(np.array([True, False, True]), np.array([True, False, False]))
# array([ True, False,  True], dtype=bool)

3

Підказка є в назві:

  • Логічні оператори призначені для виконання логічних операцій (перевірка істинності, поширена в програмуванні та формальній логіці)
  • Побітові оператори призначені для "бітового обертання" (маніпулювання бітами в байтових та числових типах даних на низькому рівні)

Хоча можливо і справді іноді бажано (зазвичай з міркувань ефективності) виконувати логічні операції з побітовими операторами, вам, як правило, слід уникати їх для таких цілей, щоб запобігти незначним помилкам та небажаним побічним ефектам.

Якщо вам потрібно маніпулювати бітами, тоді побітові оператори створені спеціально. Книга розваг: Hackers Delight містить декілька цікавих і справді корисних прикладів того, чого можна досягти за допомогою дрібниць.


2

Загальним правилом є використання відповідного оператора для існуючих операндів. Використовуйте логічні (логічні) оператори з логічними операндами та побітові оператори з (ширшими) інтегральними операндами (примітка: False еквівалентно 0 , а True до 1 ). Єдиним "хитрим" сценарієм є застосування логічних операторів до небулевих операндів.
Давайте розглянемо простий приклад, як описано в [SO]: Python - Відмінності між «і» і «&» :
5 & 7 проти 5 and 7 прогнозу .

Для побітового та ( & ), все досить просто:

5     = 0b101
7     = 0b111
-----------------
5 & 7 = 0b101 = 5

Для логічного та , ось що [Python.Docs]: Булеві операційні стани ( наголос на мені):

(Зверніть увагу , що ні і , ні або обмежувати значення і типу вони повертаються до Помилковому і правдивому , а повернути останній оцінений аргумент .

Приклад :

>>> 5 and 7
7
>>> 7 and 5
5

Звичайно, те саме стосується | проти або .


1

Логічні операції - це логічні операції.

Побітові операції - це операції над двійковими бітами.

Побітові операції:

>>> k = 1
>>> z = 3
>>> k & z  
1
>>> k | z  
3

Операції:

  • І &: 1, якщо обидва біти дорівнюють 1, інакше 0
  • АБО |: 1, якщо будь-який біт дорівнює 1, інакше 0
  • XOR ^: 1, якщо біти різні, 0, якщо вони однакові
  • NOT ~': Переверніть кожен біт

Деякі способи використання побітових операцій:

  1. Встановлення та очищення бітів

Логічні операції:

>>> k = True
>>> z = False
>>> k & z  # and
False
>>> k | z  # or
True
>>> 

1
Для булевих операцій ви не маєте на увазі "і" та "або" замість "&" та "|"?
Метью Ранкін,

Так .. Так .. Дякую, я це маю на увазі.
pyfunc

0

Логічні "та" проти побітових "&":

Псевдокод / ​​Python допоміг мені зрозуміти різницю між ними:

def boolAnd(A, B):
    # boolean 'and' returns either A or B
    if A == False:
        return A
    else:
        return B

def bitwiseAnd(A , B):
    # binary representation (e.g. 9 is '1001', 1 is '0001', etc.)

    binA = binary(A)
    binB = binary(B)



    # perform boolean 'and' on each pair of binaries in (A, B)
    # then return the result:
    # equivalent to: return ''.join([x*y for (x,y) in zip(binA, binB)])

    # assuming binA and binB are the same length
    result = []
    for i in range(len(binA)):
      compar = boolAnd(binA[i], binB[i]) 
      result.append(compar)

    # we want to return a string of 1s and 0s, not a list

    return ''.join(result)

0

Логічні операції

зазвичай використовуються для умовних тверджень. Наприклад:

if a==2 and b>10:
    # Do something ...

Це означає, що якщо обидві умови ( a==2і b>10) є істинними одночасно, тоді можна виконати тіло умовного оператора.

Побітові операції

використовуються для обробки та вилучення даних. Наприклад, якщо ви хочете витягти чотири LSB (Найменші значущі біти) цілого числа, ви можете зробити це:

p & 0xF

Питання про Python, але здавалося, що ця відповідь написана іншою мовою - можливо, Ruby? У будь-якому разі я це виправив. LMK, якщо я щось пропустив.
wjandrea
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.