3

将项目从Python转换为C#时,我在语法族中发现了一些有趣的差异。然而,我陷入了困境,仍然无法理解和理解C#中比较运算符的不同行为。运算符谜语

在治愈这种好奇心的过程中,我考虑了几种C语言家族的语言; C,C++,C#,Java,Javascript ..并验证了行为。这里是如何蒸腾:

Let a=2, b=3, c=4, d=5; 

现在,考虑下面的表达式:

a < a < a // returns true 
c < b < a // returns true 
c > b > a // returns false 
a <c> b // returns false 

如果到right-associativity是因为,然后在JavaScript下面的代码不应该像:

console.info(a < false); // returns false 
console.info(a < a);  // returns false 
console.info(a < a < a); // returns true, as opposed to returning false 

这里是C/C++版本

int main(){ 
    int a=2, b=3, c=4, d=5; 

    printf("%s\n","false\0true"+6*(a < a < a)); // returns true 
    printf("%s\n","false\0true"+6*(c < b < a)); // returns true 
    printf("%s\n","false\0true"+6*(c > b > a)); // returns false 
    printf("%s\n","false\0true"+6*(a <c> b)); // returns false 

    return 0; 
} 

除了在Python,其中

a < a < a // returns false 
c < b < a // returns false 
c > b > a // returns true 
a <c> b // returns true 

任何人都可以解释为什么C家族的语言和Python是不同的计算表达式?

+0

如果您使用文字而不是变量编写示例,此问题将更容易遵循。 – 2012-07-23 10:22:26

回答

4

由于Python uses a slightly interpretation of your input

在形式上,如果a, b, c, ..., y, z是表达式和​​op1, op2, ..., opN是比较操作符,然后a op1 b op2 c ... y opN z相当于a op1 b and b op2 c and ... y opN z,除了每个表达在评价最多一次。

这意味着你的线条将被解释为

a < a < a = a < a and a < a // returns false 
c < b < a = c < b and b < a // returns false 
c > b > a = c > b and b > a // returns true 
a <c> b = a < c and c > b // returns true 

在C语言风格的语言中,一个比较表达式将取值为false(整数值0)或true(整数值1)。因此,在C中,它会像

a < a < a = (a < a) < a = 0 < a // returns true 
c < b < a = (c < b) < a = 0 < a // returns true 
c > b > a = (c > b) > a = 1 > a // returns false 
a <c> b = (a < c) > b = 0 > b // returns false 

注意,几乎所有的语言定义运营商提供一个布尔返回值,但由于布尔值可以是隐式转换为零或一个以上的命题仍然有效:

// C++ example 
struct myComparableObject{ 
    int data; 
    bool operator<(const myComparableObject& o){ 
     return data < o.data; 
    } 
}; 

myComparableObject a, b; 
a.data = 2; 
b.data = 3; 
int c = 5; 

a < b; // true 
a < c; // error, a cannot be converted to int/unknown operator 
a.data < c; // true 
a < b < c; // true, as this is equal to 
      // (a < b) < c = false < c = 0 < c 

例如JavaScript的实际上会以两个非字符串对象比较,见[ECMAScript p78,11.8.5摘要关系比较算法],其中ToNumber(false)是零和ToNumber(true) === 1使用ToNumber

比较x < y,其中xy是值,产生truefalse,或undefined [...]

  • 让PX是调用ToPrimitive(X,暗示数)的结果。
  • 设py是调用ToPrimitive(y,hint Number)的结果。

    1. 如果不是这两种类型(PX)是字符串和类型(PY)是字符串,然后

      a.让NX是调用ToNumber(PX)的结果的情况下。因为px和py是原始值,所以评估顺序并不重要。
      b.让ny为调用ToNumber(py)的结果。
      c.如果nx是NaN,则返回undefined。
      d.如果ny是NaN,则返回undefined。
      e.如果nx和ny是相同的Number值,则返回false。
      f.如果nx为+0且ny为-0,则返回false。
      g.如果nx为-0且ny为+0,则返回false。
      h.如果nx是+ infty,则返回false。
      i.如果ny是+ infty,则返回true。
      j.如果ny是-infty,则返回false。
      k.如果nx是-infty,则返回true。
      l.如果nx的数学值小于数学值ny - 请注意,这些数学值都是有限的,但不是都为零 - 返回true。否则,返回false。
+0

请注意,Javascript稍微有点不同 - 比较返回一个布尔值,而不是整数,但是Javascript定义了一个排序顺序。 – 2012-07-20 07:26:25

+1

@NickJohnson,你能解释一下与C/C++/C#比较的变种JavaScript行为吗? – 2012-07-20 07:43:33

+1

@vulcanraven:添加了ECMAScript文档中的特定部分。 – Zeta 2012-07-20 07:53:47

2

这是因为a < a < a就像((a < a) < a)然后成为0 < a哪个是真的评价(当> = 0)

如果运行下文中,第一表达改变为false。

int main(){ 
    int a=0, b=3, c=4, d=5; 

    printf("%s\n","false\0true"+6*(a < a < a)); // returns false 
    printf("%s\n","false\0true"+6*(c < b < a)); // returns true 
    printf("%s\n","false\0true"+6*(c > b > a)); // returns false 
    printf("%s\n","false\0true"+6*(a <c> b)); // returns false 

    return 0; 
} 

而在Python中,a < a < a变得a < a and a < a。所以这不是比较a < a的结果。如果您将括号添加到您的语句中,您将再次获得类似C的行为。

(a < a) < a ## returns true 
(c < b) < a ## returns true 
(c > b) > a ## returns false 
(a < c) > b ## returns false 
+0

我没有意识到它将从左到右进行评估,而不是我们有赋值运算符'c = a 2012-07-20 09:41:16