在将项目从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 :(得分: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
,其中x
和y
是值,会生成true
,false
或undefined
[...]
- 让px成为调用ToPrimitive(x,提示号)的结果。
设py是调用ToPrimitive(y,提示号)的结果。
- 如果不是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值,则返回falsef.
如果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。
答案 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