Назначение:
Переведите следующие выражения на естественном языке в выражения C ++. Предположим, что все переменные являются неотрицательными числами или логическими (со значением true или false).
Естественный язык:
Либо a, либо b оба имеют значение false, либо c соответствует true, но не оба.
Мое решение:
(a==0 && b==0)xor(c==1)
Решение профессора:
(!a && !b) != c
Вопросов:
Я думаю, что немного понимаю первую скобку, говоря «not-a» и «not-b». Я думаю, что тогда a и b должны быть неправильными, если предположить, что ab изначально ненулевые. Правильно?
Но как насчет части, которая говорит "неравный с"?
Я не понимаю решение профессора, кто-нибудь может сломать его для меня?
Спасибо вам за помощь!
a == b or c
вместоa == b or a ==c
. Проблема в том, что разговорный язык является неточным, и фактически обе интерпретации могут быть действительнымиОтветы:
Я предполагаю , что
a
,b
иc
естьbool
.Давайте нарисуем некоторые таблицы истинности:
Как видите,
a
иa==1
эквивалентны, и!a
иa==0
также эквивалентны, поэтому мы можем переписать(a==0 && b==0)xor(c==1)
как(!a && !b) xor c
.Теперь еще несколько таблиц правды:
Так что
a!=b
эквивалентноa xor b
, так что мы можем переписать(!a && !b) xor c
в(!a && !b)!=c
. Как видите, ваши решения полностью эквивалентны, просто написаны с разными «знаками».UPD : забыл упомянуть. Есть причины, по которым решение профессора выглядит именно так.
Решение профессора более идиоматично. Хотя ваше решение технически правильно, это не идиоматический код C ++.
Первая небольшая проблема - использование типов. Ваше решение основывается на преобразовании между
int
иbool
когда вы сравниваете логическое значение с числом или использованиемxor
, которое является «побитовым эксклюзивным или» оператором, действующим также наint
s. В современном C ++ гораздо ценнее использовать значения правильных типов и не полагаться на такие преобразования, поскольку они иногда не так ясны и трудны для рассуждения. Дляbool
таких значений естьtrue
иfalse
вместо1
и0
соответственно. Это также!=
более уместно, чемxor
потому, что, хотя техническиbool
они хранятся в виде чисел, но с точки зрения семантики у вас нет никаких чисел, только логические значения.Второй вопрос касается идиоматизма. Он находится здесь:
a == 0
. Не рекомендуется сравнивать логические выражения с логическими константами. Как вы уже знаете,a == true
это полностью эквивалентно справедливомуa
иa == false
является справедливым!a
илиnot a
(я предпочитаю последнее). Чтобы понять причину, по которой это сравнение не подходит, просто сравните два фрагмента кода и решите, что более понятно:против
источник
Думай логически, а не бит
Таким образом, решение вашего профессора лучше (но все же неправильно, строго говоря, смотрите далее), потому что оно использует логические операторы вместо побитовых операторов и рассматривает логические операторы как целые числа. Выражение
c==1
для представления «c является истинным» является неправильным, потому что, если c может быть числом (в соответствии с заявленным присваиванием), тогда любое ненулевое значение c следует рассматривать как представляющееtrue
.Посмотрите на этот вопрос, почему лучше не сравнивать логические значения с 0 или 1, даже если это безопасно.
Одна очень веская причина не использовать
xor
это то, что это побитовое исключение или операция. Это работает в вашем примере, потому что и левая, и правая части являются логическими выражениями, которые преобразуются в 1 или 0 (см. Снова 1 ).Булево исключение - или есть на самом деле
!=
.Разбивая выражение
Чтобы лучше понять решение вашего преподавателя, проще всего заменить логические операторы их эквивалентами «альтернативного токена», что превращает его в более читаемый (imho) и полностью эквивалентный код C ++: использование «not» для «!» и 'и' для '&&' вы получаете
К сожалению, нет логического
exclusive_or
оператора, кромеnot_eq
, который не помогает в этом случае.Если мы разобьем выражение на естественном языке:
сначала в предложении о булевых предложениях A и B:
это переводится в
A != B
(только для логических значений, а не для любых типов A и B).Тогда предложение А было
который может быть заявлен как
который переводит в
(not a and not b)
, и, наконец,Который просто переводит на
c
. Объединяя их, вы получаете снова(not a and not b) != c
.Для дальнейшего объяснения того, как тогда работает это выражение, я приведу таблицы истинности, которые другие дали в своих ответах.
Вы оба не правы
И если я могу придираться: в первоначальном присваивании говорилось, что a, b и c могут быть неотрицательными числами, но не однозначно указывалось, что если бы они были числами, они должны быть ограничены значениями 0 и 1. Если любое число является не 0 представляет
true
, как обычно, тогда следующий код даст неожиданный ответ :источник
a
,b
иc
объявлены какbool
, в этом случаеc == 1
является правильным , хотя и зверского кода. В любом случае, это ответ, который я бы написал: код OP может быть эквивалентен коду профессора, но это плохо на C ++.variables are non-negative numbers or boolean
. Так что +1 к @dhavenith от меня за то, что я уловил детали, которые пропустили большинство других здесь (включая меня, изначально).Я попытаюсь объяснить с помощью еще нескольких слов: числа могут быть неявно преобразованы в логические значения:
Источник на cppreference
Это приводит к следующим выводам:
a == 0
так же, как!a
, потому чтоa
преобразуется в логическое значение, а затем инвертируется, что равно!(a != 0)
. То же самое касается б.c==1
станет истинным только приc
равенстве 1. Использование преобразования(bool)c
даст результат,true
аc != 0
не только еслиc == 1
. Так что это может работать, потому что обычно для представления используется значение 1true
, но это не гарантируется.a != b
то же самое, чтоa xor b
когдаa
иb
ar булевы выражения. Это правда, когда одно значение или другое верно, но не оба. В этом случае левая часть(a==0 && b==0)
является логической, поэтому правая часть такжеc
преобразуется в логическую, поэтому обе стороны интерпретируются как логические выражения, таким образом!=
, то же самое, что иxor
в этом случае.Вы можете проверить все это самостоятельно с помощью правдивых таблиц, предоставленных другими ответами.
источник
Как мы видим из таблиц истинности:
!
(not
) и==0
дают одинаковые результаты.!=
иxor
дать те же результаты.c==1
так же, как простоc
Так одно под другим показывает, почему эти два выражения дают одинаковый результат:
Таблицы правды:
Не
== 0
== 1
А также
Не равный
XOR
источник