Недавно я столкнулся с проблемой, которая требовала от меня определения логического оператора «ИЛИ» программно, но без использования самого оператора.
Я придумал вот что:
OR(arg1, arg2)
if arg1 = True and arg2 = True
return True
else if arg1 = True and arg2 = False
return True
else if arg1 = False and arg2 = True
return True
else:
return False
Правильна ли эта логика, или я что-то упустил?
programming-logic
logicNoob
источник
источник
return arg1 ? arg1 : arg2;
or
оператора.Ответы:
Я бы сказал, что это правильно, но не могли бы вы сократить это до чего-то такого?
Поскольку вы делаете сравнение или сравнение, я не думаю, что вам действительно нужно проверять комбинацию. Это просто имеет значение, если один из них верен, чтобы вернуть истину. В противном случае мы хотим вернуть false.
Если вы ищете более короткую версию, которая менее многословна, это также будет работать:
источник
if arg2 == true
).or(a, b): a ? a : b
Вот решение без или, и, не, сравнений и логических литералов:
Это, вероятно, не становится намного более фундаментальным, чем это;)
источник
true
илиfalse
.||
В двух словах оператор JavaScript (при реализации на динамически типизированном языке).Одна строка кода:
Нет ветвления, нет ИЛИ.
На языке Си это будет:
Это просто применение законов де Моргана :
(A || B) == !(!A && !B)
источник
if/else
конструкция такая же, как использование OR, только с другим именем.if
эквивалентно равенству. Обычно в машинном коде anif
реализуется в виде арифметики с последующим сравнением с нулем с помощью скачка.and
, обеспечивая согласованность между операторами.if (a) return true; else if (b) return true;
кажется более или менее морально эквивалентнымif (a OR b) return true;
, но эта точка зрения вполне может быть открыта для обсуждения.Если у вас есть только
and
иnot
, вы можете использовать закон Деморгана, чтобы перевернутьand
:... или (еще проще)
...
И поскольку все мы, очевидно, зациклились на оптимизации чего-то, что почти всегда доступно как машинная инструкция, это сводится к:
и тд и тд и тп
Так как большинство языков предоставляют условные-и, коэффициенты - это оператор "и" в любом случае подразумевает переход.
...
Если все, что у вас есть
nand
(см. Википедию ):вернуть nand (nand (arg1, arg1), nand (arg2, arg2))
источник
return not (not arg1 and not arg2)
nand
раствором.Функции (ECMAScript)
Все, что вам нужно, это определения функций и вызовы функций. Вам не нужны никакие ветвления, условия, операторы или встроенные функции. Я продемонстрирую реализацию с использованием ECMAScript.
Во-первых, давайте определим две функции с именем
true
иfalse
. Мы можем определить их так, как хотим, они совершенно произвольны, но мы определим их совершенно особым образом, что имеет некоторые преимущества, как мы увидим позже:tru
это функция с двумя параметрами, которая просто игнорирует второй аргумент и возвращает первый.fls
также является функцией с двумя параметрами, которая просто игнорирует свой первый аргумент и возвращает второй.Почему мы кодировали
tru
иfls
так? Ну, таким образом, две функции не только представляют две концепцииtrue
иfalse
, нет, они также представляют концепцию «выбора», другими словами, они также являютсяif
/then
/else
выражением! Мы оцениваемif
условие и передаем емуthen
блок иelse
блок в качестве аргументов. Если условие оценивается какtru
, оно возвращаетthen
блок, если оно оцениваетfls
, оно возвращаетelse
блок. Вот пример:Это возвращается
23
, и это:возвращается
42
, как и следовало ожидать.Есть морщина, однако:
Это печатает оба
then branch
иelse branch
! Зачем?Ну, он возвращает возвращаемое значение первого аргумента, но он оценивает оба аргумента, поскольку ECMAScript является строгим и всегда оценивает все аргументы функции перед вызовом функции. IOW: он оценивает первый аргумент
console.log("then branch")
, который просто возвращает,undefined
и имеет побочный эффект печатиthen branch
на консоль, и он оценивает второй аргумент, который также возвращаетundefined
и печатает на консоль как побочный эффект. Затем возвращается первоеundefined
.В λ-исчислении, где было изобретено это кодирование, это не проблема: λ-исчисление чисто , что означает, что оно не имеет побочных эффектов; поэтому вы никогда не заметите, что второй аргумент также оценивается. Кроме того, λ-исчисление является ленивым (или, по крайней мере, его часто оценивают в обычном порядке), то есть фактически не оценивает аргументы, которые не нужны. Итак, IOW: в λ-исчислении второй аргумент никогда не будет оцениваться, и если бы это было так, мы бы этого не заметили.
ECMAScript, однако, является строгим , то есть он всегда оценивает все аргументы. Ну, на самом деле, не всегда:
if
/then
/else
, например, только оцениваетthen
ветвь, если условие есть,true
и только оцениваетelse
ветвь, если условие естьfalse
. И мы хотим повторить это поведение с нашимиiff
. К счастью, несмотря на то, что ECMAScript не ленив, у него есть способ отложить оценку фрагмента кода, точно так же, как это делает почти любой другой язык: обернуть его в функцию, и если вы никогда не вызовете эту функцию, код будет никогда не будет казнен.Итак, мы заключаем оба блока в функцию, и в конце вызываем возвращаемую функцию:
печатает
then branch
иотпечатки
else branch
.Мы могли бы реализовать традиционный
if
/then
/else
таким образом:Опять же, нам нужна дополнительная упаковка функций при вызове
iff
функции и дополнительные скобки вызова функции в определенииiff
, по той же причине, что и выше:Теперь, когда у нас есть эти два определения, мы можем их реализовать
or
. Сначала мы смотрим на таблицу истинностиor
: если первый операнд является правдивым, то результат выражения совпадает с первым операндом. В противном случае, результат выражения является результатом второго операнда. Вкратце: если первый операндtrue
, мы возвращаем первый операнд, в противном случае мы возвращаем второй операнд:Давайте проверим, что это работает:
Большой! Однако это определение выглядит немного некрасиво. Помните,
tru
иfls
уже сами по себе действуйте как условные, так что на самом деле в этом нет необходимостиiff
, и, следовательно, все эти функции оборачиваются вообще:Там у вас есть это:
or
(плюс другие логические операторы) определены только с определениями функций и вызовами функций всего за несколько строк:К сожалению, эта реализация довольно бесполезна: в ECMAScript нет функций или операторов, которые возвращают
tru
илиfls
, все они возвращаютtrue
илиfalse
, поэтому мы не можем использовать их с нашими функциями. Но мы все еще можем многое сделать. Например, это реализация односвязного списка:Объекты (Скала)
Возможно, вы заметили что-то своеобразное:
tru
и,fls
играя двойную роль, они действуют как значения данныхtrue
иfalse
, в то же время, они также действуют как условное выражение. Это данные и поведение , объединенные в один ... хм ... "предмет" ... или (смею сказать) объект !Действительно,
tru
иfls
есть объекты. И, если вы когда-либо использовали Smalltalk, Self, Newspeak или другие объектно-ориентированные языки, вы заметите, что они реализуют булевы значения точно таким же образом. Я продемонстрирую такую реализацию здесь, в Scala:Вот почему, кстати, всегда работает функция «Заменить условное на полиморфное рефакторинг»: вы всегда можете заменить любое условное выражение в вашей программе полиморфной отправкой сообщений, потому что, как мы только что показали, полиморфная диспетчеризация сообщений может заменить условные выражения, просто внедрив их. Такие языки, как Smalltalk, Self и Newspeak, являются доказательством существования, потому что у этих языков нет даже условных выражений. (У них также нет циклов, BTW или вообще каких- либо встроенных в язык структур управления, кроме полиморфной отправки сообщений, называемых вызовами виртуальных методов.)
Pattern Matching (Haskell)
Вы также можете определить,
or
используя сопоставление с образцом или что-то вроде определения частичной функции Haskell:Конечно, сопоставление с образцом является формой условного выполнения, но опять же, как и объектно-ориентированная отправка сообщений.
источник
False ||| False = False
и_ ||| _ = True
вместо? :)True ||| undefined
себя в ghci, чтобы увидеть!Вот еще один способ определить ИЛИ или любой другой логический оператор, используя самый традиционный способ его определения: использовать таблицу истинности.
Это, конечно, довольно тривиально в языках более высокого уровня, таких как Javascript или Perl, но я пишу этот пример на C, чтобы показать, что техника не зависит от особенностей языка высокого уровня:
Вы можете сделать то же самое с AND, NOR, NAND, NOT и XOR. Код достаточно чистый, чтобы выглядеть как синтаксис, так что вы можете делать что-то вроде этого:
источник
BinaryOperator or = new TruthTableBasedBinaryOperator(new TruthTable(false, true, true, true));
Еще один способ выразить логические операторы в виде целочисленных арифметических выражений (где это возможно). Таким образом можно избежать большого количества ветвлений для большего выражения многих предикатов.
Пусть True будет 1 Пусть False будет 0
если сумма обоих значений больше 1, то это будет true или false, чтобы быть возвращенным.
источник
booleanExpression ? true : false
тривиально равноbooleanExpression
.return (arga+argb)>0
return (((arg1 ? 1 : 0)+(arg2 ? 1 : 0)) > 0);
:)arg1 ? 1 : 0;
. Это надежные выражения для преобразования логического числа в число. Это только оператор возврата, который может быть тривиально реорганизован.Две формы:
ИЛИ
И, кроме того, у кода есть преимущество в виде гольфа, так как он немного меньше других предложений, на одну ветку меньше. Это даже не то глупое микро-решение, чтобы уменьшить количество ветвей, если мы рассматриваем создание примитива, который, следовательно, будет очень интенсивно использоваться.
Определение Javascript
||
сродни этому, что в сочетании с его свободной типизацией означает, что выражениеfalse || "abc"
имеет значение"abc"
и42 || "abc"
имеет значение42
.Хотя, если у вас уже есть другие логические операторы, то подобное
nand(not(arg1), not(arg2))
может иметь преимущество в том, что ветвления вообще нет.источник
В дополнение ко всем запрограммированным решениям, использующим конструкцию if, можно создать вентиль ИЛИ путем объединения трех вентилей NAND. Если вы хотите увидеть, как это делается в википедии, нажмите здесь .
Из этого выражения
который использует NOT и AND дает тот же ответ, что и OR. Обратите внимание, что использование как NOT, так и AND является просто неясным способом выражения NAND.
источник
Все хорошие ответы уже даны. Но я не позволю этому остановить меня.
В качестве альтернативы:
Я надеюсь, что никто никогда не будет использовать такие подходы. Они здесь только для повышения осведомленности об альтернативах.
Обновить:
Поскольку отрицательные числа могут нарушить оба вышеуказанных подхода, вот еще одно ужасное предложение:
Это просто использует законы Деморгана и злоупотребляет тем, что
*
похоже на то,&&
когдаtrue
и сfalse
которыми обращаются как1
и0
соответственно. (Подожди, ты говоришь, что это не код гольф?)Вот достойный ответ:
Но это по сути идентично другим ответам, которые уже даны.
источник
arg1+arg2
, -1 и 0 дляmax(arg1,arg2)
и т. Д.Один из способов определить
or
это с помощью таблицы поиска. Мы можем сделать это явно:мы создаем массив со значениями, которые возвращаемое значение должно иметь в зависимости от того, что
a
есть. Тогда мы делаем поиск. В языках, подобных C ++,bool
повышается до значения, которое можно использовать в качестве индекса массива сtrue
бытием1
иfalse
бытием0
.Затем мы можем распространить это на другие логические операции:
Недостатком всего этого является то, что требуется префиксная нотация.
и теперь вы можете напечатать,
true *OR* false
и это работает.Приведенная выше методика требует языка, который поддерживает поиск, зависящий от аргументов, и шаблонов. Возможно, вы могли бы сделать это на языке с генериками и ADL.
Кроме того, вы можете расширить
*OR*
вышеперечисленное для работы с наборами. Просто создайте свободную функциюinvoke
в том же пространстве имен, что иor_tag
:и теперь
set *OR* set
возвращает союз двух.источник
Этот вспоминает мне характерные функции:
Это относится только к языкам, которые могут трактовать логические значения как (1, 0). Не применяется к Smalltalk или Python, так как логический класс является классом. В smalltalk они идут еще дальше (это будет написано в виде псевдокода):
А двойные методы существуют для и:
Таким образом, «логика» совершенно верна в операторе OP, хотя и многословна. Осторожно, это не плохо. Идеально, если вам нужна функция, которая действует как математический оператор, например, на основе своего рода матрицы. Другие будут реализовывать фактический куб (например, оператор Quine-McCluskey):
И вы будете оценивать или [a] [b]
Так что да, каждая логика здесь действительна (кроме той, которая опубликована с использованием оператора ИЛИ языка xDDDDDDDD).
Но мой любимый закон Деморгана:
!(!a && !b)
источник
Посмотрите на стандартную библиотеку Swift и проверьте их реализацию операций быстрого доступа ИЛИ и быстрого вызова И, которые не оценивают вторые операнды, если они не нужны / не разрешены.
источник
Логика совершенно правильная, но ее можно упростить:
И, вероятно, у вашего языка есть оператор ИЛИ, поэтому - если это не противоречит духу вопроса - почему бы и нет
источник
if arg1 = True or arg2 = True { return true } else { return false }
Еще лучшеreturn arg1 = True or arg2 = True
.if condition then true else false
избыточно