Помимо AND/OR/NOT, какой смысл в других логических операторах в программировании?
Я программировал почти всю свою жизнь (около 20+ лет), и я не думаю, что могу вспомнить хоть один раз, когда я смотрел на выражение if и думал: "Хм, это было бы хорошим временем для используйте XOR." Вся вселенная логического программирования, кажется, вращается вокруг этих трех.
Конечно, с помощью логических элементов И / ИЛИ / НЕ вы можете сделать любое другое логическое утверждение. Однако может быть время, когда вам удастся сэкономить некоторый код для объединения двух или трех операторов в один логический оператор. Давайте посмотрим на 16 возможных комбинаций логических связок:
- ЛОЖЬ = Противоречие = 0, ноль, НЕ ИСТИНА
- ИСТИНА = Тавтология = 1, НЕ ЛОЖЬ
- X = предложение X = X
- НЕ Х = Отрицание Х =! Х
- Y = предложение Y = Y
- НЕ Y = отрицание Y =! Y
- X И Y = Соединение = НЕ (X И НЕ Y)
- X NAND Y = Альтернативный отказ = НЕ (X И Y),! X ИЛИ! Y
- X ИЛИ Y = дизъюнкция = НЕ (! X И! Y)
- X NOR Y = Объединенный отказ = НЕ (X ИЛИ Y),! X И! Y
- X ⊅ Y = Материальная неявность = X И! Y, НЕ (! X ИЛИ Y), (X XOR Y) И X,???
- X ⊃ Y = Материальное значение =! X ИЛИ Y, НЕ (X И! Y), (X XNOR Y) ИЛИ X,???
- X ⊄ Y = обратное неявное выражение =! X И Y, НЕ (X ИЛИ! Y), (X XOR Y) И Y,???
- X ⊂ Y = обратное значение = X ИЛИ! Y, НЕ (! X И Y), (X XNOR Y) ИЛИ Y,???
- X XOR Y = Исключительная дизъюнкция = НЕ (X IFF Y), НЕ (X XNOR Y), X! = Y
- X XNOR Y = Biconditional = X IFF Y, НЕ (X XOR Y),! X AND! Y
Таким образом, пункты 1-2 содержат нулевые переменные, пункты 3-6 включают одну, а пункты 7-10 - термины, с которыми мы знакомы. (Хотя у нас обычно нет оператора NAND, но, по крайней мере, в Perl есть "разве что" для универсального NOT.)
Пункты 11-14 кажутся интересными, но я никогда не видел их в программировании. Пункты 15-16 являются XOR/XNOR.
Может ли что-либо из этого быть использовано для упрощения И / ИЛИ / НЕ? Если да, то использовали ли вы их?
ОБНОВЛЕНИЕ: "Не равно" или! = Действительно XOR, который используется постоянно. Итак, XOR используется в конце концов.
6 ответов
Собираюсь закрыть этот вопрос после вещи Не равно /XOR. Из 16 возможных операторов программисты используют 9 из них:
FALSE, TRUE, X, Y, !X, !Y, AND (or ==), OR, XOR (or !=)
Все остальные операторы обычно не существуют в языках программирования:
X NAND Y = Alternative Denial = NOT (X AND Y), !X OR !Y
X NOR Y = Joint Denial = NOT (X OR Y), !X AND !Y
X ⊅ Y = Material Nonimplication = X AND !Y, NOT(!X OR Y), (X XOR Y) AND X, ???
X ⊃ Y = Material Implication = !X OR Y, NOT(X AND !Y), (X XNOR Y) OR X, ???
X ⊄ Y = Converse Nonimplication = !X AND Y, NOT(X OR !Y), (X XOR Y) AND Y, ???
X ⊂ Y = Converse Implication = X OR !Y, NOT(!X AND Y), (X XNOR Y) OR Y, ???
X XNOR Y = Biconditional = X IFF Y, NOT (X XOR Y), !X AND !Y
Возможно, им есть место позже, потому что NAND/NOR кажется довольно удобным и более чистым, чем ввод NOT (X xxx Y).
"Пункты 11-14 кажутся интересными, но я никогда не видел их в программировании".
Я не согласен. Пункт 12, "Материальный эффект", по сути, является утверждением "ЕСЛИ", он везде в программировании. Я вижу Материальные последствия такие же как:
if(A) {
return B
}
Учти это:
if(an odd number of conditions are true) then return 1 else return 0
Используя и / или / нет, вы можете попробовать
if(one is true || three are true || ... 2n+1 are true) then return 1 else return 0
Это довольно уродливо, потому что вам приходится указывать каждый из 1-наборов, 3-наборов, 5-наборов, ..., 2n+1 наборов, которые являются подмножествами набора ваших условий. Версия XOR довольно элегантна, хотя...
if(C1 XOR C2 XOR ... XOR CN) then return 1 else return 0
Для больших или переменных N это, вероятно, лучше обрабатывать с помощью системы циклов и счетчиков, но когда N не слишком велико (~10), и вы еще не сохраняете условия в виде массива, это не так так плохо. Работает так же для проверки четного числа условий.
Вы можете придумать похожие примеры и для других. Интересным упражнением было бы попробовать программировать что-то вроде
if((A && !B) || (!A && B)) then return 1 else return 0
И посмотрите, генерирует ли компилятор язык ассемблера для AND, OR и NOT или достаточно умен, чтобы признать, что это XOR, и, основываясь на этом, испускает (возможно, более дешевую) инструкцию XOR.
При программировании на Java я обычно использую следующие логические функции:
- не
!
- а также
&&
- или же
||
- XNOR
==
- исключающее
!=
,
распространяя это на другие основные функции:
- материальное значение
A || !B
- обратное значение
!A || B
- материальная неявность
!A && B
- обратное неявное
A && !B
Знание того, когда использовать xor и xnor, сводится к упрощению логики. В общем, когда у вас сложная функция:
1) упростить до CNF ("конъюнктивная нормальная форма" или "сумма над произведением") или DNF ("дизъюнктивная нормальная форма" или "произведение над суммой").*
2) удалить дополнительные условия A && (A || B)
,A || (A && B)
-> A
2) упростить (A || !B) && (!A || B)
,(!A && !B) || (A && B)
-> A == B
3) упростить (A || B) && (!A || !B)
,(A && !B) || (!A && B)
-> A != B
Использование этих трех упрощений может привести к получению более чистого кода с использованием функций xor и xnor.
* Следует отметить, что логическая функция может быть намного проще в DNF, чем в CNF или наоборот.
Существенный вариант использования без импликации / абстракции
Теперь у меня есть пример, в котором я хотел бы сделать материальное непересечение / аббревиатуру .
Таблица правды
╔═══╦═══╦══════════╗
║ P ║ Q ║ P -/-> Q ║
╠═══╬═══╬══════════╣
║ T ║ T ║ F ║
║ T ║ F ║ T ║ <-- all I care about. True followed by false.
║ F ║ T ║ F ║
║ F ║ F ║ F ║
╚═══╩═══╩══════════╝
Я имею дело с несколькими разрешениями (все к счастью /
false
) для нескольких сущностей одновременно и имею ситуацию с ролями и правами, в которой я хочу увидеть, может ли системный пользователь изменить права другого пользователя. Та же операция выполняется сразу для всех сущностей.
Во-первых, мне нужна разница между старым состоянием разрешений объекта и новым обычно желаемым состоянием разрешений для всех объектов.
Затем я хочу сравнить эту дельту с правами на изменение текущего пользователя для этой конкретной сущности.
- Меня не волнуют разрешения, когда дельта не требует изменения.
- Я хочу только
true
флаг, где действие должно быть заблокировано.
Пример
before: 10001
proposed after: 11001
delta: 01000 <<< I want a material nonimplication...
user rights 10101 <<< ... between these two...
blocked actions: 01000 <<< ... to produce this flag set
Прямо сейчас я просто делаю
XOR
а затем
AND
, что одно и то же.
Какой-то код пахнет тем, что есть более простой способ провести сравнение, но, по крайней мере, в этой невероятно громоздкой, пошаговой логике было бы неплохо иметь этот оператор.
Я считаю, что материальное непонимание на самом деле представлено
A && !B
(ответ Бретту Ярберри)