Du langage naturel à l'expression C ++

9

Affectation:

Traduisez les expressions de langage naturel suivantes en expressions C ++. Supposons que toutes les variables sont des nombres non négatifs ou booléens (de valeur true ou false).

Langage naturel:

Soit a et b sont faux ou c est vrai, mais pas les deux.

Ma solution:

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

Solution professeurs:

(!a && !b) != c

Des questions:

  1. Je pense que je comprends un peu la première tranche, en disant "pas-a" et "pas-b" je pense que a et b doivent alors être faux, à condition que ab soit supposé non nul au début. Droite?

  2. Mais qu'en est-il de la partie qui dit "inégal à c"?

  3. Je ne comprends pas la solution Professeurs, quelqu'un peut-il la décomposer pour moi?

Merci pour l'aide!

limonade
la source
en général, je serais prudent avec la traduction des expressions booléennes de la langue parlée en code. Une erreur courante consiste à traduire "A est égal à B ou C" en au a == b or clieu de a == b or a ==c. Le problème est que le langage parlé est imprécis et que les deux interprétations pourraient être valides
idclev 463035818

Réponses:

5

Je suppose que a, bet csont bool.

Tirons quelques tables de vérité:

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

Comme vous pouvez le voir, aet a==1sont équivalents, et !aet a==0sont également équivalents, nous pouvons donc réécrire (a==0 && b==0)xor(c==1)en (!a && !b) xor c.

Maintenant, quelques tables de vérité supplémentaires:

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

Donc , a!=best équivalent à a xor b, donc on peut réécrire (!a && !b) xor cà (!a && !b)!=c. Comme vous le voyez, vos solutions sont entièrement équivalentes, juste écrites avec différents «signes».


UPD : J'ai oublié de mentionner. Il y a des raisons pour lesquelles la solution du professeur ressemble exactement à cela.

La solution du professeur est plus idiomatique. Bien que votre solution soit techniquement correcte, ce n'est pas un code C ++ idiomatique.

Le premier petit problème est l'utilisation des types. Votre solution repose sur la conversion entre intet boollorsque vous comparez la valeur booléenne à un nombre ou à une utilisation xor, qui est également un opérateur «exclusif au niveau du bit» ou agissant sur les ints. Dans un C ++ moderne, il est beaucoup plus apprécié d'utiliser des valeurs de types corrects et de ne pas se fier à de telles conversions car elles ne sont parfois pas aussi claires et difficiles à raisonner. Car boolces valeurs sont trueet falseau lieu de 1et 0respectivement. Est également !=plus approprié que xorparce que, techniquement, les bools sont stockés sous forme de nombres, mais sémantiquement vous n'avez pas de nombres, juste des valeurs logiques.

Le deuxième problème concerne également l'idiomatie. Il se trouve ici: a == 0. Il n'est pas considéré comme une bonne pratique de comparer des expressions booléennes à des constantes booléennes. Comme vous le savez déjà, a == trueest entièrement équivalent à juste a, et a == falseest juste !aou not a(je préfère ce dernier). Pour comprendre la raison pour laquelle cette comparaison n'est pas bonne, il suffit de comparer deux extraits de code et de décider, ce qui est plus clair:

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

contre

if (not str.empty()) { ... }
Yuri Kovalenko
la source
1
Bien que techniquement correcte, cette réponse évite complètement de parler des types et du C ++ idiomatique, qui étaient probablement le but de cet exercice.
Konrad Rudolph
@KonradRudolph, oh, ouais, j'ai complètement oublié de le mentionner. Peut-être que je vais modifier ma réponse, merci
Yuri Kovalenko
3

Pensez aux booléens, pas aux morceaux

En résumé, la solution de votre professeur est meilleure (mais toujours fausse, à proprement parler, voir plus loin) car elle utilise des opérateurs booléens au lieu d'opérateurs au niveau du bit et traite les booléens comme des entiers. L'expression c==1pour représenter "c est vrai" est incorrecte car si c peut être un nombre (selon l'affectation indiquée), alors toute valeur non nulle de c doit être considérée comme représentative true.

Consultez cette question pour savoir pourquoi il est préférable de ne pas comparer les booléens à 0 ou 1, même lorsque cela est sûr.

Une très bonne raison de ne pas l'utiliser xorest qu'il s'agit de l' opération ou de l'exclusivité bit à bit . Il se trouve que cela fonctionne dans votre exemple, car le côté gauche et le côté droit sont des expressions booléennes qui se convertissent en 1 ou 0 (voir à nouveau 1 ).

Le booléen exclusif ou est en fait !=.

Décomposer l'expression

Pour mieux comprendre la solution de votre professeur, il est plus facile de remplacer les opérateurs booléens par leurs équivalents de "jeton alternatif", ce qui en fait un code C ++ mieux réductible (à mon humble avis) et complètement équivalent: en utilisant 'not' for '!' et 'et' pour '&&' vous obtenez

    (not a and not b) != c

Malheureusement, il n'y a aucun exclusive_oropérateur logique autre que not_eq, ce qui n'est pas utile dans ce cas.

Si nous décomposons l'expression du langage naturel:

Soit a et b sont faux ou c est vrai, mais pas les deux.

d'abord dans une phrase sur les propositions booléennes A et B:

Soit A ou B, mais pas les deux.

cela se traduit par A != B(uniquement pour les booléens, pas pour les types A et B).

Alors la proposition A était

a et b sont tous deux faux

qui peut être déclaré comme

a est faux et b est faux

qui se traduit par (not a and not b), et enfin

c est vrai

Ce qui se traduit simplement par c. En les combinant, vous obtenez à nouveau (not a and not b) != c.

Pour plus d'explications sur le fonctionnement de cette expression, je m'en remets aux tables de vérité que d'autres ont données dans leurs réponses.

Vous vous trompez tous les deux

Et si je peux me moquer de moi: l'affectation d'origine a déclaré que a, b et c peuvent être des nombres non négatifs, mais n'a pas déclaré sans ambiguïté que s'il s'agissait de nombres, ils devraient être limités aux valeurs 0 et 1. Si un nombre quelconque est pas 0 représente true, comme c'est la coutume, alors le code suivant donnerait une réponse surprenante :

    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);

dhavenith
la source
Eh bien a, espérons-le , bet csont déclarés comme bool, dans ce cas , le code c == 1est correct , mais atroce. Quoi qu'il en soit, c'est la réponse que j'aurais écrite: le code OP peut être équivalent au professeur, mais c'est du mauvais C ++.
Konrad Rudolph
1
@KonradRudolph Du texte d'affectation OP: variables are non-negative numbers or boolean. Donc +1 à @dhavenith de ma part pour avoir saisi un détail que la plupart des autres ici ont manqué (y compris moi, au départ).
Frodyne
Génial, Isee. Je vous remercie! Mais pouvez-vous alors m'expliquer la solution de mon professeur parce que je ne la comprends pas.
limonade
J'ai ajouté une orthographe alternative pour la solution de votre professeur. Cela devrait aider à clarifier l'expression. Pour des explications plus détaillées, je pense que les tables de vérité dans la réponse de @YuriKovalenko sont la meilleure façon d'approcher l'expression.
dhavenith
2

Je vais essayer d'expliquer avec quelques mots: les nombres peuvent être implicitement convertis en valeurs booléennes:

La valeur zéro (pour l'énumération intégrale, à virgule flottante et non étendue) et le pointeur nul et les valeurs pointeur-à-membre nul deviennent faux. Toutes les autres valeurs deviennent vraies.

Source sur cppreference

Cela conduit aux conclusions suivantes:

  • a == 0est identique à !a, car aest converti en booléen puis inversé, ce qui équivaut à !(a != 0). Il en va de même pour b.

  • c==1deviendra vrai que lorsque c est égal à 1. À l' aide de la conversion (bool)cproduirait truequand c != 0non seulement si c == 1. Cela peut donc fonctionner, car on utilise généralement la valeur 1 pour représenter true, mais ce n'est pas garanti.

  • a != best identique à a xor bwhen aet à bdes expressions booléennes. C'est vrai, quand une valeur ou l'autre est vraie, mais pas les deux. Dans ce cas, le côté gauche (a==0 && b==0)est booléen, donc le côté droit cest également converti en booléen, ainsi, les deux côtés sont interprétés comme des expressions booléennes, c'est donc !=la même chose que xordans ce cas.

Vous pouvez vérifier tout cela vous-même avec les tables de vérité fournies par les autres réponses.

churill
la source
2

Comme nous pouvons le voir sur les tables de vérité:

  • !( not) et ==0donnent les mêmes résultats.
  • !=et xordonner les mêmes résultats.
  • c==1 est le même que juste c

Donc, l'une sous l'autre, montre pourquoi ces 2 expressions donnent le même résultat:

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

Tables de vérité:

ne pas

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

== 0

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

== 1

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

Et

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

Inégal

   | 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 |
Robert Andrzejuk
la source