自然言語からC ++式へ


9

割り当て:

以下の自然言語式をC ++式に変換します。すべての変数が負でない数値またはブール値(値trueまたはfalse)であると仮定します。

自然言語:

aとbの両方が偽であるか、cが真であるが、両方ではない。

私の解決策:

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

教授のソリューション:

(!a && !b) != c

質問:

  1. 「not-a」と「not-b」と言って、最初の括弧を少し理解したと思います。abが最初はゼロ以外であると仮定すると、aとbは間違っていると思います。正しい?

  2. しかし、「cに等しくない」と言っている部分はどうでしょうか。

  3. 教授の解決策が理解できません。誰かが私のために解決できますか?

お手伝いありがとう!


一般に、話し言葉のブール式をコードに変換する際には注意が必要です。よくある間違いは、「AはBまたはCと等しい」をのa == b or c代わりにに変換することですa == b or a ==c。問題は、話し言葉が不正確であり、実際には両方の解釈が有効である可能性があることです
idclev 463035818

回答:


5

私はそれを仮定しますabcしていますbool

真理値表をいくつか描いてみましょう。

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

ご覧のとおり、aおよびa==1は同等であり!aa==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 ++コードではありません。

最初の小さな問題は型の使い方です。あなたのソリューションは、間の変換に依存しているintboolあなたは数や使用にブール値を比較するときxorに作用する「ビット単位の排他的論理和」演算子であり、intあまりに秒。最近のC ++では、正しい型の値を使用し、そのような変換がそれほど明確でなく推論するのが難しい場合があるため、そのような変換に依存しないことがはるかに高く評価されています。そのboolような値については、それぞれtrue、およびfalse代わりに、1および0です。また、技術的にはsは数値として格納されますが、意味的には数値がなく、論理値だけなので、!=より適切です。xorbool

2番目の問題は、慣用性についてもです。それはここにあります:a == 0。ブール式をブール定数と比較することは良い習慣とは見なされていません。既にご存じのように、a == trueはjustと完全に同等でaa == falseただ!aorですnot a(私は後者を好みます)。その比較がうまくいかない理由を理解するには、2つのコードスニペットを比較して決定するだけです。

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

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

1
技術的には正しいですが、この答えは、おそらくこの演習のポイントだった型や慣用的なC ++について話すことを完全に避けます。
Konrad Rudolph

@KonradRudolph、ああ、ええ、私はそれについて言及するのを完全に忘れていました。たぶん私は私の答えを編集します、ありがとう
Yuri Kovalenko

3

ビットではなくブール値を考える

要約すると、教授の解決策はビット演算子ではなくブール演算子を使用し、ブール値を整数として扱うため、より優れています(ただし、厳密には間違っています。c==1「cはtrue」を表す式は正しくありません。cが(指定された割り当てに従って)数値である場合、cのゼロ以外の値はを表すと見なされるためtrueです。

安全であるとしてもブール値を0または1と比較しない方がよい理由については、この質問を参照してください。

使用しない非常に良い理由の1つxorは、これがビット単位の排他的OR演算であることです。これは、左側と右側の両方が1または0に変換されるブール式であるため、例では偶然に機能します(再度1を参照)。

ブール排他的ORは実際には!=です。

表現を分解する

教授のソリューションをよりよく理解するには、ブール演算子を同等の「代替トークン」に置き換えるのが最も簡単です。これにより、より優れた再入力可能(imho)で完全に同等のC ++コードに変換されます。そして、あなたが得る「&&」の「そして」

    (not a and not b) != c

残念ながら、以外には論理exclusive_or演算子not_eqはありません。この場合、これは役に立ちません。

自然言語表現を分解すると:

aとbの両方が偽であるか、cが真であるが、両方ではない。

最初にブール命題AとBについての文に:

AまたはBのいずれかです。両方は使用できません。

これは次のように変換されますA != B(ブールAとBではなくブール型のみ)。

次に、命題Aは

aとbは両方ともfalse

これは

aはfalse、bはfalse

これはに変換され(not a and not b)、最後に

cはtrue

これは単にに変換されcます。それらを組み合わせると、再び得られ(not a and not b) != cます。

この表現がどのように機能するかをさらに説明するために、私は他の人が答えで示した真理値表を参照します。

あなたは両方間違っています

そして、私がちょっと気になるかもしれない場合:元の割り当てでは、a、b、cは負でない数値でもかまわないと述べていましたが、数値の場合は値0と1に制限する必要があることを明確に述べていませんでした。true通常ではないように0はを表さないため、次のコードは驚くべき答えをもたらします

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

まあうまくいけばabcのように宣言されboolた場合には、c == 1ある正しい凶悪コードものの、。とにかく、これは私が書いただろう答えです。OPのコードは教授のコードと同等かもしれませんが、それは悪いC ++です。
Konrad Rudolph

1
OPの割り当てテキストから@KonradRudolph: variables are non-negative numbers or boolean。したがって、ここにいる他のほとんどの人が見落とした詳細をキャッチしてくれた@dhavenithに+1(最初は私を含めて)。
Frodyne

いいですね。ありがとうございました!しかし、私には理解できないので、私の教授の解決策を説明してくれませんか。
リモネード

教授の解決策に代替スペルを追加しました。これは、表現を明確にするのに役立ちます。詳細な説明については、@ YuriKovalenkoの回答の真理値表が式にアプローチする最良の方法だと思います。
dhavenith

2

私はいくつかの言葉で説明しようとします:数値は暗黙的にブール値に変換できます:

値ゼロ(整数、浮動小数点、およびスコープなし列挙の場合)およびnullポインターとnullポインターからメンバーへの値はfalseになります。他のすべての値はtrueになります。

cppreferenceのソース

これは、次の結論につながります。

  • a == 0はブール値に変換されてから反転される!aためa、と同じです!(a != 0)。同じことがbにも言えます。

  • c==1場合にのみ真になりますc 等しい変換を使用して1を(bool)cもたらすであろうtrueときc != 0だけでなく、場合c == 1。だから、できる 1は通常、表現するために値1を使用しているため、動作しtrueますが、それはgarantuedていません。

  • a != ba xor bwhen 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 |
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.