Від природної мови до виразу С ++


9

Призначення:

Перекладіть такі вирази природних мов у вирази C ++. Припустимо, що всі змінні є негативними числами або булевими (значення true або false).

Природна мова:

Або a, і b є і хибними, або c є істинними, але не обидва.

Моє рішення:

(a==0 && b==0)xor(c==1)

Рішення професора:

(!a && !b) != c

Запитання:

  1. Я думаю, що я трохи розумію першу дужку, кажучи "не-а" і "не-b", я думаю, що a і b повинні бути помилковими, якщо ab на початку вважається ненульовим. Правильно?

  2. Але як щодо тієї частини, яка говорить "нерівна с"?

  3. Я не розумію рішення професорів, чи може хтось зламати це для мене?

Дякую за допомогу!


в цілому я би був обережним з перекладом булевих виразів розмовної мови в код. Поширена помилка - перекласти "A дорівнює B або C" a == b or cзамість a == b or a ==c. Проблема полягає в тому, що розмовна затримка є неточною і насправді обидві інтерпретації можуть бути дійсними
idclev 463035818

Відповіді:


5

Я припускаю , що a, bі cє bool.

Давайте намалюємо кілька таблиць істини:

| a | !a | a==1 | a==0 |
| 0 |  1 |   0  |   1  |
| 1 |  0 |   1  |   0  |

Як ви можете бачити, aі a==1еквівалентні, а !aі a==0також еквівалентні, так що ми можемо переписати в (a==0 && b==0)xor(c==1)вигляді (!a && !b) xor c.

Тепер ще кілька таблиць правди:

| a | b | a xor b | a != b |
| 0 | 0 |    0    |    0   |
| 0 | 1 |    1    |    1   |
| 1 | 0 |    1    |    1   |
| 1 | 1 |    0    |    0   |

Так що a!=bеквівалентно a xor b, так що ми можемо переписати (!a && !b) xor cв (!a && !b)!=c. Як бачите, ваші рішення повністю еквівалентні, просто написані з різними «знаками».


UPD : Забув згадати. Є причини, чому рішення професора виглядає саме так.

Рішення професора є більш ідіоматичним. Хоча ваше рішення технічно правильне, це не ідіоматичний код C ++.

Перша маленька проблема - використання типів. Ваше рішення покладається на перетворення між intі boolпри порівнянні булевого значення на число або використання xor, що є "біт-розумним ексклюзивом" або "оператором, що діє і на ints. У сучасному C ++ набагато приємніше використовувати значення правильних типів і не покладатися на такі перетворення, оскільки вони іноді не так зрозумілі і важко обґрунтувати. Для boolтаких значень є trueі falseзамість, 1і 0відповідно. Також !=є більш підходящим, ніж xorтому, що, якщо технічно bools зберігаються як числа, але сематично у вас немає чисел, а лише логічні значення.

Друге питання також стосується ідіотизму. Він знаходиться тут: a == 0. Не вважається хорошою практикою порівнювати булеві вирази з булевими константами. Як ви вже знаєте, a == trueповністю еквівалентний справедливому aі a == falseє справедливим !aабо not a(я віддаю перевагу останньому). Щоб зрозуміти причину, чому порівняння не є добрим, просто порівняйте два фрагменти коду та вирішіть, що зрозуміліше:

if (str.empty() == false) { ... }

проти

if (not str.empty()) { ... }

1
Хоча технічно правильна, ця відповідь повністю уникає розмов про типи та ідіоматичні C ++, які, ймовірно, були пунктом цієї вправи.
Конрад Рудольф

@KonradRudolph, о, так, я зовсім забув це згадати. Можливо, я відредагую свою відповідь, дякую
Юрій Коваленко

3

Думайте, булі, а не шматочки

Підсумовуючи це, рішення вашого професора є кращим (але все-таки неправильним, строго кажучи, див. Далі), оскільки він використовує булові оператори замість розрядних операторів і трактує булеві числа як цілі числа. Вираз c==1для позначення "c є істинним" є невірним, тому що якщо c може бути числом (згідно з заявленим призначенням), то будь-яке ненульове значення c повинно вважатися репрезентуючим true.

Дивіться це запитання щодо того, чому краще не порівнювати булеви з 0 або 1, навіть коли це безпечно.

Однією з дуже вагомих причин не користуватися xorє те, що це експрес- ексклюзив чи операція. Це трапляється у вашому прикладі, тому що і ліва, і права сторона є булевими виразами, які перетворюються на 1 або 0 (див. Знову 1 ).

Булева ексклюзивна або є насправді !=.

Розбиття виразу

Щоб краще зрозуміти рішення вашого професора, найпростіше замінити булеві оператори на їх "альтернативні лексеми" еквівалентами, що перетворює його на кращу редагуваність (imho) та повністю еквівалентний код C ++: Використання "не" для "!" і ви отримаєте "і" за && "

    (not a and not b) != c

На жаль, немає жодного логічного exclusive_orоператора, окрім цього not_eq, що не допомагає в цьому випадку.

Якщо ми розбиваємо природний вираз мови:

Або a, і b є і хибними, або c є істинними, але не обидва.

спочатку в реченні про булеві пропозиції А і В:

Або А, або В, але не обидва.

це означає A != B(лише для булевих, а не для будь-якого типу A і B).

Тоді пропозиція А була

a і b є хибними

які можна констатувати як

a - хибна, а b - хибна

що перекладається на (not a and not b), і нарешті

c - це правда

Що просто перекладається на c. Поєднуючи їх, ви отримуєте знову (not a and not b) != c.

Для подальшого пояснення того, як працює цей вираз, я відкладаю до таблиць істинності, які інші дали у своїх відповідях.

Ви обоє помиляєтесь

І якщо я можу нітрик: Оригінальне завдання зазначало, що a, b і c можуть бути невід'ємними числами, але не однозначно зазначало, що якщо вони були числами, вони повинні бути обмежені значеннями 0 і 1. Якщо є якесь число, яке є не 0 являє собою true, як це прийнято, тоді наступний код дасть дивовижну відповідь :

    auto c = 2; // "true" in some way
    auto a = 0; // "false"
    auto b = 0; // "false"

    std::cout << ((!a && !b) != c);

// this will output: 1 (!)
// fix by making sure that != compares booleans:

    std::cout << ((!a && !b) != (bool)c);

Ну , сподіваюся a, bі cоголошені як bool, в цьому випадку c == 1є правильним , хоча і звірячого коду. У всякому разі, це я відповідь, яку я написав би: код ОП може бути еквівалентний професорському, але це погано С ++.
Конрад Рудольф

1
@KonradRudolph З тексту присвоювання OP в: variables are non-negative numbers or boolean. Тож +1 від мене @dhavenith за те, що я зрозумів деталь, яку більшість інших тут пропустили (включаючи мене, спочатку).
Фродіне

Чудово, я бачу. Дякую! Але чи можете ви потім пояснити мені рішення мого професора, тому що я його не розумію.
лимонад

Я додав альтернативне написання для рішення вашого професора. Це повинно допомогти уточнити вираз. Для більш детальних пояснень я вважаю, що таблиці правди у відповіді від @YuriKovalenko - це найкращий спосіб підійти до висловлення.
dhavenith

2

Спробую пояснити ще кількома словами: Числа можна неявно перетворити на булеві значення:

Значення нуля (для інтеграла, з плаваючою комою та незаписаним перерахуванням) та нульового вказівника та нульових значень вказівника на член стають помилковими. Усі інші значення стають істинними.

Джерело на cppreference

Це призводить до таких висновків:

  • a == 0те саме !a, що aперетворюється на булевий, а потім інвертований, що дорівнює !(a != 0). Те саме стосується і b.

  • c==1стане істинним лише тоді, коли c дорівнює 1. Використання конверсії (bool)cдасть результат, trueколи c != 0не просто так c == 1. Так це може працювати, тому що зазвичай використовується значення 1 для представлення true, але воно не гарантується.

  • a != bте саме, що a xor bколи aі bar булеві вирази. Це правда, коли одна чи інша цінність є правдою, але не те й інше. У цьому випадку ліва сторона (a==0 && b==0)булева, тому права рука cперетворена в булева, таким чином, обидві сторони інтерпретуються як булеві вирази, таким чином, !=це те саме, що і xorв цьому випадку.

Ви можете перевірити все це самостійно за допомогою правдивих даних, які надали інші відповіді.


2

Як ми бачимо з таблиць правди:

  • !( not) і ==0дають ті самі результати.
  • !=і xorдають ті самі результати.
  • c==1 те саме, що просто c

Так один під іншим показує, чому ці 2 вирази дають однаковий результат:

(a==0 && b==0) xor (c==1)
(!a   && !b)   !=   c

Таблиці правди:

Ні

    |   | ! |
    | 0 | 1 |
    | 1 | 0 |

== 0

    |   |==0|
    | 0 | 1 |
    | 1 | 0 |

== 1

    |   |==1|
    | 0 | 0 |
    | 1 | 1 |

І

   | a | b | && |
   | 0 | 0 |  0 |
   | 0 | 1 |  0 |
   | 1 | 0 |  0 |
   | 1 | 1 |  1 |

Не рівні

   | a | b | != |
   | 0 | 0 |  0 |
   | 0 | 1 |  1 |
   | 1 | 0 |  1 |
   | 1 | 1 |  0 |

XOR

   | a | b |xor|
   | 0 | 0 | 0 |
   | 0 | 1 | 1 |
   | 1 | 0 | 1 |
   | 1 | 1 | 0 |
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.