操作员谜语

时间:2012-07-20 06:57:37

标签: algorithm programming-languages comparison operators imperative-programming

在将项目从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系列以不同的方式计算表达式吗?

2 个答案:

答案 0 :(得分: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实际上会使用ToNumber来比较两个非字符串对象,参见[ECMAScript p78,11.8.5抽象关系比较算法],其中ToNumber(false)为零和ToNumber(true) === 1

  

比较x < y,其中xy是值,会生成truefalseundefined [...]

     
      
  • 让px成为调用ToPrimitive(x,提示号)的结果。
  •   
  • 设py是调用ToPrimitive(y,提示号)的结果。

         
        
    1. 如果不是Type(px)都是String而Type(py)是String,那么

        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。
    2.   
  •   

答案 1 :(得分:2)

这是因为a < a < a被评估为((a < a) < a),然后变为0 < a,这是真的(当&gt; = 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