Von der natürlichen Sprache zum C ++ - Ausdruck

9

Zuordnung:

Übersetzen Sie die folgenden Ausdrücke in natürlicher Sprache in C ++ - Ausdrücke. Angenommen, alle Variablen sind nicht negative Zahlen oder Boolesche Werte (mit dem Wert true oder false).

Natürliche Sprache:

Entweder a und b sind beide falsch oder c ist wahr, aber nicht beide.

Meine Lösung:

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

Professorenlösung:

(!a && !b) != c

Fragen:

  1. Ich denke, ich verstehe die erste Klammer ein wenig, indem ich "nicht-a" und "nicht-b" sage. Ich denke, dass a und b dann falsch sein müssen, vorausgesetzt, ab wird am Anfang als ungleich Null angenommen. Recht?

  2. Aber was ist mit dem Teil, der "ungleich c" sagt?

  3. Ich verstehe die Professors-Lösung nicht. Kann jemand sie für mich aufschlüsseln?

Danke für die Hilfe!

Limonade
quelle
Im Allgemeinen würde ich vorsichtig sein, wenn ich boolesche Ausdrücke in gesprochener Sprache in Code übersetze. Ein häufiger Fehler besteht darin, "A gleich B oder C" in a == b or cstatt zu übersetzen a == b or a ==c. Das Problem ist, dass die gesprochene Sprache ungenau ist und tatsächlich beide Interpretationen gültig sein könnten
idclev 463035818

Antworten:

5

Ich gehe davon aus, dass a, bund csind bool.

Lassen Sie uns einige Wahrheitstabellen zeichnen:

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

Wie Sie sehen können, aund a==1sind gleichwertig und !aund a==0sind auch gleich, so können wir umschreiben (a==0 && b==0)xor(c==1)als (!a && !b) xor c.

Nun noch ein paar Wahrheitstabellen:

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

So a!=bentspricht a xor b, so schreiben wir können (!a && !b) xor czu (!a && !b)!=c. Wie Sie sehen, sind Ihre Lösungen völlig gleichwertig, nur mit unterschiedlichen "Zeichen" geschrieben.


UPD : Vergessen zu erwähnen. Es gibt Gründe, warum die Lösung des Professors genau so aussieht.

Die Lösung des Professors ist idiomatischer. Ihre Lösung ist zwar technisch korrekt, aber kein idiomatischer C ++ - Code.

Das erste kleine Problem ist die Verwendung von Typen. Ihre Lösung basiert auf der Konvertierung zwischen intund boolbeim Vergleichen des Booleschen Werts mit einer Zahl oder Verwendung xor. Dies ist ein "bitweiser Exklusiv" - oder "Operator", der auch auf ints einwirkt . In einem modernen C ++ wird es viel mehr geschätzt, Werte vom richtigen Typ zu verwenden und sich nicht auf solche Konvertierungen zu verlassen, da diese manchmal nicht so klar und schwer zu begründen sind. Für boolsolche Werte sind trueund falsestatt 1und 0sind. Auch !=ist besser geeignet, als xorweil technisch bools als Zahlen gespeichert sind, aber sematisch haben Sie keine Zahlen, nur logische Werte.

In der zweiten Ausgabe geht es auch um Redewendung. Es liegt hier : a == 0. Es wird nicht als bewährte Methode angesehen, boolesche Ausdrücke mit booleschen Konstanten zu vergleichen. Wie Sie bereits wissen, a == trueist völlig gleichbedeutend mit gerecht aund a == falseist gerecht !aoder not a(ich bevorzuge letzteres). Um den Grund zu verstehen, warum dieser Vergleich nicht gut ist, vergleichen Sie einfach zwei Codefragmente und entscheiden Sie, was klarer ist:

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

vs.

if (not str.empty()) { ... }
Yuri Kovalenko
quelle
1
Diese Antwort ist zwar technisch korrekt, vermeidet jedoch vollständig, über Typen und idiomatisches C ++ zu sprechen, die vermutlich der Punkt dieser Übung waren.
Konrad Rudolph
@KonradRudolph, oh ja, ich habe völlig vergessen, das zu erwähnen. Vielleicht werde ich meine Antwort bearbeiten, danke
Yuri Kovalenko
3

Denken Sie an Boolesche Werte, nicht an Bits

Zusammenfassend ist die Lösung Ihres Professors besser (aber genau genommen immer noch falsch, siehe weiter unten), da sie boolesche Operatoren anstelle von bitweisen Operatoren verwendet und Boolesche Werte als Ganzzahlen behandelt. Der Ausdruck c==1für "c ist wahr" ist falsch, denn wenn c eine Zahl sein kann (gemäß der angegebenen Zuordnung), ist jeder Wert ungleich Null von c als repräsentativ anzusehen true.

In dieser Frage erfahren Sie, warum es besser ist, Boolesche Werte nicht mit 0 oder 1 zu vergleichen, auch wenn dies sicher ist.

Ein sehr guter Grund, nicht zu verwenden, xorist, dass dies die bitweise Exklusivität oder Operation ist. In Ihrem Beispiel funktioniert dies zufällig, da sowohl die linke als auch die rechte Seite boolesche Ausdrücke sind, die in 1 oder 0 konvertiert werden (siehe erneut 1 ).

Das boolesche Exklusiv-Oder ist in der Tat !=.

Den Ausdruck aufschlüsseln

Um die Lösung Ihres Professors besser zu verstehen, ist es am einfachsten, die booleschen Operatoren durch ihre "alternativen Token" -Äquivalente zu ersetzen, wodurch sie in besser redigierbaren (imho) und vollständig äquivalenten C ++ - Code umgewandelt werden: Verwenden von 'not' for '!' und 'und' für '&&' bekommen Sie

    (not a and not b) != c

Leider gibt es keinen exclusive_oranderen logischen Operator als not_eq, was in diesem Fall nicht hilfreich ist.

Wenn wir den Ausdruck der natürlichen Sprache auflösen:

Entweder a und b sind beide falsch oder c ist wahr, aber nicht beide.

zuerst in einen Satz über die Booleschen Sätze A und B:

Entweder A oder B, aber nicht beide.

Dies bedeutet A != B(nur für Boolesche Werte, nicht für Typ A und B).

Dann war Satz A.

a und b sind beide falsch

was als angegeben werden kann

a ist falsch und b ist falsch

was übersetzt in (not a and not b)und schließlich

c ist wahr

Was einfach übersetzt bedeutet c. Wenn du sie kombinierst, bekommst du wieder (not a and not b) != c.

Zur weiteren Erklärung, wie dieser Ausdruck dann funktioniert, verweise ich auf die Wahrheitstabellen, die andere in ihren Antworten angegeben haben.

Sie sind beide falsch

Und wenn ich nicht picken darf: Die ursprüngliche Zuordnung besagte, dass a, b und c nicht negative Zahlen sein können, gab aber nicht eindeutig an, dass sie, wenn sie Zahlen wären, auf die Werte 0 und 1 beschränkt werden sollten Nicht 0 bedeutet true, wie üblich, dann würde der folgende Code eine überraschende Antwort liefern :

    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
quelle
Na hoffentlich a, bund cdeklariert als bool, in diesem Fall c == 1ist richtig , obwohl atrocious Code. Jedenfalls ist dies die Antwort, die ich geschrieben hätte: Der Code von OP entspricht möglicherweise dem des Professors, aber es ist schlechtes C ++.
Konrad Rudolph
1
@KonradRudolph Aus dem Zuweisungstext von OP : variables are non-negative numbers or boolean. Also +1 an @dhavenith von mir, weil ich ein Detail gefunden habe, das die meisten anderen hier übersehen haben (einschließlich mir anfangs).
Frodyne
Großartig, Isee. Vielen Dank! Aber können Sie mir dann die Lösung meines Professors erklären, weil ich sie nicht verstehe?
Limonade
Ich habe eine alternative Schreibweise für die Lösung Ihres Professors hinzugefügt. Dies sollte helfen, den Ausdruck zu verdeutlichen. Für detailliertere Erklärungen denke ich, dass die Wahrheitstabellen in der Antwort von @YuriKovalenko der beste Weg sind, sich dem Ausdruck zu nähern.
Dhavenith
2

Ich werde versuchen, mit einigen weiteren Worten zu erklären: Zahlen können implizit in boolesche Werte konvertiert werden:

Der Wert Null (für Integral-, Gleitkomma- und Aufzählung ohne Gültigkeitsbereich) sowie der Nullzeiger- und der Nullzeiger-zu-Element-Wert werden falsch. Alle anderen Werte werden wahr.

Quelle auf cppreference

Dies führt zu folgenden Schlussfolgerungen:

  • a == 0ist das gleiche wie !a, weil ain einen Booleschen Wert konvertiert und dann invertiert wird, was gleich ist !(a != 0). Gleiches gilt für b.

  • c==1wird nur wahr, wenn c gleich 1. Die Verwendung der Konvertierung (bool)cwürde ergeben, truewenn c != 0nicht nur wenn c == 1. So kann es funktionieren, weil man normalerweise den Wert 1 verwendet, um darzustellen true, aber es ist nicht garantiert.

  • a != bist dasselbe wie a xor bwhen aund bar boolesche Ausdrücke. Es ist wahr, wenn der eine oder andere Wert wahr ist, aber nicht beide. In diesem Fall ist die linke Seite (a==0 && b==0)boolesch, daher wird auch die rechte Seite cin einen Booleschen Wert konvertiert. Daher werden beide Seiten als boolesche Ausdrücke interpretiert und sind somit !=dieselben wie xorin diesem Fall.

Sie können dies alles selbst anhand der Wahrheitstabellen überprüfen, die in den anderen Antworten angegeben sind.

churill
quelle
2

Wie wir aus den Wahrheitstabellen sehen können:

  • !( not) und ==0geben die gleichen Ergebnisse.
  • !=und xorgeben die gleichen Ergebnisse.
  • c==1 ist das gleiche wie gerade c

So zeigt einer unter dem anderen, warum diese beiden Ausdrücke das gleiche Ergebnis liefern:

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

Wahrheitstabellen:

Nicht

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

== 0

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

== 1

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

Und

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

Nicht gleich

   | 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
quelle