简体   繁体   English

从自然语言到 C++ 表达式

[英]From natural language to C++ expression

Assignment:任务:

Translate the following natural language expressions to C++ expressions.将以下自然语言表达式转换为 C++ 表达式。 Assume that all the variables are non-negative numbers or boolean (of value true or false).假设所有变量都是非负数或布尔值(值为真或假)。

Natural Language:自然语言:

Either a and b are both false or c is true, but not both. a 和 b 都为假或 c 为真,但不能同时为真。

My solution:我的解决方案:

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

Professors solution:教授解决方案:

(!a && !b) != c

Questions:问题:

  1. I think I slightly understand the first bracket, by saying "not-a" and "not-b" I think that a and b must then be wrong, provided ab are assumed to be non-zero in the beginning.我想我稍微理解了第一个括号,通过说“not-a”和“not-b”,我认为 a 和 b 一定是错误的,前提是 ab 在开始时被假定为非零。 Right?对?

  2. But what about the part that says "unequal to c"?但是说“不等于c”的部分呢?

  3. I don't understand the Professors solution, can anyone break it down for me?我不明白教授的解决方案,谁能帮我分解一下?

Thank you for the help!感谢您的帮助!

I'll assume that a , b and c are bool .我假设a , bcbool

Let's draw some truth tables:让我们画一些真值表:

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

As you can see, a and a==1 are equivalent, and !a and a==0 are also equivalent, so we can rewrite (a==0 && b==0)xor(c==1) as (!a && !b) xor c .可以看到, aa==1是等价的, !aa==0也是等价的,所以我们可以将(a==0 && b==0)xor(c==1)改写为(!a && !b) xor c

Now some more truth tables:现在还有一些真值表:

| 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!=b is equivalent to a xor b , so we can rewrite (!a && !b) xor c to (!a && !b)!=c .所以a!=b等价于a xor b ,所以我们可以将(!a && !b) xor c重写为(!a && !b)!=c As you see, your solutions are fully equivalent, just written with different 'signs'.如您所见,您的解决方案完全等效,只是用不同的“符号”编写。


UPD : Forgot to mention. UPD :忘记提及了。 There are reasons why professor's solution looks exactly in that way.教授的解决方案看起来完全那样是有原因的。

The professor's solution is more idiomatic.教授的解决方案更加地道。 While your solution is technically correct, it's not an idiomatic C++ code.虽然您的解决方案在技术上是正确的,但它不是惯用的 C++ 代码。

First little issue is usage of types.第一个小问题是类型的使用。 Your solution relies on conversion between int and bool when you compare boolean value to a number or use xor , which is a 'bit-wise exclusive or' operator acting on int s too.当您将布尔值与数字进行比较或使用xor ,您的解决方案依赖于intbool之间的转换, xor也是作用于int的“按位异或”运算符。 In a modern C++ it is much more appreciated to use values of correct types and not to rely on such conversions as they're sometimes not so clear and hard to reason about.在现代 C++ 中,使用正确类型的值而不是依赖于这种转换,因为它们有时不是那么清楚和难以推理,这是更受欢迎的。 For bool such values are true and false instead of 1 and 0 respectively.对于bool这些值分别为truefalse而不是10 Also != is more appropriate than xor because while technically bool s are stored as numbers, but sematically you haven't any numbers, just logical values.此外!=xor更合适,因为虽然技术上bool s 存储为数字,但从语义上讲,您没有任何数字,只有逻辑值。

Second issue is about idiomacy too.第二个问题也是关于成语的。 It lies here: a == 0 .它就在这里: a == 0 It is not considered a good practice to compare boolean expressions to boolean constants.将布尔表达式与布尔常量进行比较不是一个好习惯。 As you already know, a == true is fully equivalent to just a , and a == false is just !a or not a (I prefer the latter).正如您已经知道的那样, a == true完全等同于a ,而a == false只是!anot a (我更喜欢后者)。 To understand the reason why that comparing isn't good just compare two code snippets and decide, which is clearer:要了解这种比较不好的原因,只需比较两个代码片段并做出决定,就更清楚了:

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

vs对比

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

Think booleans, not bits想想布尔值,而不是位

In summary, your professor's solution is better (but still wrong, strictly speaking, see further down) because it uses boolean operators instead of bitwise operators and treating booleans as integers.总而言之,您教授的解决方案更好(但严格来说仍然是错误的,请往下看),因为它使用布尔运算符而不是按位运算符并将布尔值视为整数。 The expression c==1 to represent "c is true" is incorrect because if c may be a number (according to the stated assignment) then any non-zero value of c is to be regarded as representing true .表示“c 为真”的表达式c==1是不正确的,因为如果 c 可能是一个数字(根据规定的赋值),那么 c 的任何非零值都将被视为表示true

See this question on why it's better not to compare booleans with 0 or 1, even when it's safe to do so.请参阅此问题,了解为什么最好不要将布尔值与 0 或 1 进行比较,即使这样做是安全的。

One very good reason not to use xor is that this is the bit-wise exclusive or operation.不使用xor一个很好的理由是,这是按异或运算。 It happens to work in your example because both the left hand side and right hand side are boolean expressions that convert to 1 or 0 (see again 1 ).它恰好适用于您的示例,因为左侧和右侧都是转换为 1 或 0 的布尔表达式(再次参见1 )。

The boolean exclusive-or is in fact != .布尔异或实际上是!=

Breaking down the expression分解表达式

To understand your professor's solution better, it's easiest to replace the boolean operators with their "alternative token" equivalents, which turns it into better redable (imho) and completely equivalent C++ code: Using 'not' for '!'为了更好地理解教授的解决方案,最简单的方法是将布尔运算符替换为它们的“替代标记”等价物,这将其变成更好的 redable (imho) 和完全等效的 C++ 代码:使用 'not' for '!' and 'and' for '&&' you get和 'and' 为 '&&' 你得到

    (not a and not b) != c

Unfortunately, there is no logical exclusive_or operator other than not_eq , which isn't helpful in this case.不幸的是,除了not_eq之外没有逻辑上的exclusive_or运算符,这在这种情况下没有帮助。

If we break down the natural language expression:如果我们分解自然语言表达式:

Either a and b are both false or c is true, but not both. a 和 b 都为假或 c 为真,但不能同时为真。

first into a sentence about boolean propositions A and B:首先进入关于布尔命题 A 和 B 的句子:

Either A or B, but not both. A 或 B,但不能两者兼而有之。

this translates into A != B (only for booleans, not for any type A and B).这转化为A != B (仅适用于布尔值,不适用于任何类型 A 和 B)。

Then proposition A was那么命题 A 是

a and b are both false a 和 b 都是假的

which can be stated as可以表示为

a is false and b is false a 是假的,b 是假的

which translates into (not a and not b) , and finally转化为(not a and not b) ,最后

c is true c 是真的

Which simply translates into c .这简单地转换为c Combining them you get again (not a and not b) != c .将它们结合起来,你又得到了(not a and not b) != c

For further explanation how this expression then works, I defer to the truth tables that others have given in their answers.为了进一步解释这个表达式是如何工作的,我遵循其他人在他们的答案中给出的真值表。

You're both wrong你们都错了

And if I may nitpick: The original assignment stated that a, b and c can be non-negative numbers, but did not unambiguously state that if they were numbers, they should be limited to the values 0 and 1. If any number that is not 0 represents true , as is customary, then the following code would yield a surprising answer :如果我可以吹毛求疵:最初的分配说明 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);

As we can see from the truth tables:正如我们从真值表中看到的:

  • ! ( not ) and ==0 give the same results. ( not ) 和==0给出相同的结果。
  • != and xor give the same results. !=xor给出相同的结果。
  • c==1 is the same as just c c==1c

So one under the other, shows why these 2 expressions give the same result:所以一个在另一个下面,说明为什么这两个表达式给出相同的结果:

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

Truth tables :真值表:

Not不是

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

==0 ==0

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

==1 ==1

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

And

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

Not equal不相等

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

I will tryto explain with some more words: Numbers can be implicitly converted to boolean values:我将尝试用更多的话来解释:数字可以隐式转换为布尔值:

The value zero (for integral, floating-point, and unscoped enumeration) and the null pointer and the null pointer-to-member values become false.零值(对于整数、浮点和无作用域枚举)以及空指针和指向成员的空指针值变为假。 All other values become true.所有其他值都变为真。

Source on cppreference cppreference 上的来源

This leads to the following conclusions:这导致以下结论:

  • a == 0 is the same as !a , because a is converted to a boolean and then inverted, which equals !(a != 0) . a == 0!a相同,因为a被转换为布尔值然后反转,等于!(a != 0) The same goes for b. b 也是如此。

  • c==1 will become only true when c equals 1. Using the conversion (bool)c would yield true when c != 0 not just if c == 1 . c==1仅在c等于1 时才变为真。使用转换(bool)c将在c != 0时产生true ,而不仅仅是在c == 1 So it can work, because one usually uses the value 1 to represent true , but it's not garantued.所以它可以工作,因为人们通常使用值 1 来表示true ,但它没有保证。

  • a != b is the same as a xor b when a and b ar boolean expressions.ab布尔表达式时, b a != ba xor b相同。 It's true, when one value or the other is true, but not both.这是真的,当一个值或另一个为真时,但不是两者都为真。 In this case the left hand side (a==0 && b==0) is boolean, so the right hand side c is converted to boolean too, thus, both sides are interpreted as boolean expressions, thus != is the same as xor in this case.在这种情况下,左边(a==0 && b==0)是布尔值,所以右边c被转换为布尔值,因此,两边都被解释为布尔表达式,因此!=与在这种情况下xor

You can check all of this yourself with the truthtables that the other answers provided.您可以使用其他答案提供的真值表自行检查所有这些。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM