在PHP中进行types杂耍和(严格)大于/小于比较
PHP以其types杂耍而闻名。 我必须承认这使我困惑,而且我很难在比较中找出基本的逻辑/基本的东西。
例如:如果$a > $b
为真, $b > $c
为真,那么它是否意味着$a > $c
总是为真?
遵循基本的逻辑,我会说是的,但是我感到困惑,我不太信任在这个PHP。 也许有人可以提供一个例子,如果不是这样的话?
另外我想知道严格的小于和严格的大于运算符(因为它们的含义被严格地描述为我只知道在过去从等式比较),如果左和右操作数交换严格不平等的价值观:
# Precondition: if ($a === $b) { throw new Exception( 'Both are strictly equal - can not compare strictly for greater or smaller' ); } ($a > $b) !== ($b > $a)
对于大多数types比较组合,这些较大/较小的比较运算符都没有logging,因此在这种情况下阅读手册并不是很有帮助。
PHP的比较运算符在几个方面偏离了计算机科学的定义:
为了构成一个等价关系, ==
必须是自反的,对称的和传递的:
-
PHP的
==
运算符不是自反的 ,即$a == $a
并不总是对的:var_dump(NAN == NAN); // bool(false)
注意:任何涉及
NAN
比较总是false
的事实并不是PHP特有的。 它是由IEEE 754浮点运算标准( 更多信息 )规定的。 -
PHP的
==
运算符是对称的 ,即$a == $b
和$b == $a
总是相同的。 -
PHP的
==
运算符不是传递的 ,即从$a == $b
和$b == $c
不符合$a == $c
:var_dump(true == "a"); // bool(true) var_dump("a" == 0); // bool(true) var_dump(true == 0); // bool(false)
为了构成偏序 <=
/ >=
必须是自反的,反对称的和传递性的:
-
PHP的
<=
运算符不是自反的 ,即$a <= $a
并不总是为真(例子与==
相同)。 -
PHP的
<=
运算符不是反对称的 ,即从$a <= $b
和$b <= $a
不符合$a == $b
:var_dump(NAN <= "foo"); // bool(true) var_dump("foo" <= NAN); // bool(true) var_dump(NAN == "foo"); // bool(false)
-
PHP的
<=
运算符不是传递的 ,即从$a <= $b
和$b <= $c
不跟随$a <= $c
(例子与==
相同)。 -
额外:PHP的
<=
运算符不是总数 ,即$a <= $b
和$b <= $a
都可以是false:var_dump(new stdClass <= new DateTime); // bool(false) var_dump(new DateTime <= new stdClass); // bool(false)
为了构成严格的偏序 ,必须是非reflection的,不对称的和传递性的:
-
PHP的
<
运算符是不reflection的 ,即$a < $a
永远不会是真的。 请注意,这仅仅是从PHP 5.4开始的 。 以前INF < INF
评估为true
。 -
PHP的
<
运算符不是不对称的 ,即从$a < $b
不跟随!($b < $a)
(示例与<=
不是反对称)相同。 -
PHP的
<
操作符不是传递的 ,即从$a < $b
和$b < $c
不跟随$a < $c
:var_dump(-INF < 0); // bool(true) var_dump(0 < TRUE); // bool(true) var_dump(-INF < TRUE); // bool(false)
-
额外:PHP的
<
运算符不是三元的 ,也就是说,$a < $b
,$b < $a
和$a == $b
都可以是假的(例子与<=
不是总和)相同。 -
额外:PHP的
<
运算符可以是循环的 ,也就是说$a < $b
,$b < $c
和$c < $a
:var_dump(INF < []); // bool(true) var_dump([] < new stdClass); // bool(true) var_dump(new stdClass < INF); // bool(true)
注意:上面的例子抛出了“stdClass类的对象无法转换为double”通知。
您可以在PHP悲伤52 -比较运算符上find一些关于PHP比较运算符的漂亮图表。
作为最后一点,我想指出的是,PHP 确实有两个平等点(几乎与其他所有方面不同)。 这两者总是成立,只是因为编译器将一个减less到另一个:
($a > $b) == ($b < $a) ($a >= $b) == ($b <= $a)
PHP中没有 严格相同的比较运算符( >==
或<==
) (至lessPHP 5.6.14) ,但有几种方法在检查Greater / Lower之前强制进行严格types检查 :
- 用
if (gettype($a) === gettype($b))
检查两个variablestypes - 强制你需要的types转换例如。
if ((string)$a === (string)$b)
- 强制你需要的types,例如。
if (($a . '') === ($b . ''))
请注意:
- 浮点精度有限
-
INF
和NAN
是ieee754下的浮点types - 有些Infinity等于其他Infinity (自PHP 5.4以来)
- 科学记数法
e
始终为float
types,即使数字很小也不会integer
- 整数遍历
PHP_INT_MAX
会自动转换为float
- 漂浮在系统的边界上获得
INF
值 - 未定义variables的types和值为
NULL
- 以
0
结尾的整数从八进制转换为十进制(按照惯例) - 将包含具有前导
0
的整数的string转换为整数将删除前导0
一些奇特的比较列表:
很奇怪: $ a VS. $ b $ a> $ b $ a <$ b $ a <= $ b $ a> = $ b $ a == $ b $ a === $ b 浮点(NAN)浮点数(-INF)假假假假假假假 浮点(NAN)浮点(0)假假假假假假假 float(NAN)float(1)false false false false false 浮点(NAN)浮点(INF)假假假假假假假 浮点(NAN)浮点(NAN)假假假假假假假 float(NAN)int(-1)false false false false false float(NAN)int(0)false false false false false float(NAN)int(1)false false false false false
相同但不相同:
$ a VS. $ b $ a> $ b $ a <$ b $ a <= $ b $ a> = $ b $ a == $ b $ a === $ b
NULL(NULL)array()false false true true true false NULL(NULL)bool(false)false false true true false NULL(NULL)float(0)false false true true false NULL(NULL)int(0)false false true true false NULL(NULL)str('')false false true true false array()bool(false)false false true true false bool(false)float(0)false false true true false bool(false)int(0)false false true true false str('')bool(false)false false true true false bool(false)str('0')false false true true false float(-INF)bool(true)false false true true true false bool(true)float(1)false false true true false float(INF)bool(true)false false true true false float(NAN)bool(true)false false true true true false bool(true)int(-1)false false true true false bool(true)int(1)false false true true false bool(true)str(“\ 0”)false false true true false bool(true)str('+')false false true true true false bool(true)str(' - ')false false true true false bool(true)str('01')false false true true true false bool(true)str('1')false false true true true false bool(true)str('false')false false true true true false str('text')bool(true)false false true true false str('true')bool(true)false false true true false int(0)float(0)false false true true false str(“\ 0”)float(0)false false true true false str('')float(0)false false true true false str('+')float(0)false false true true true false str(' - ')float(0)false false true true false str('0')float(0)false false true true false str('false')float(0)false false true true false str('text')float(0)false false true true false str('true')float(0)false false true true false int(1)float(1)false false true true false float(1)str('01')false false true true true false float(1)str('1')false false true true true false str(“\ 0”)int(0)false false true true false str('')int(0)false false true true false str('+')int(0)false false true true false str(' - ')int(0)false false true true false int(0)str('0')false false true true true false str('false')int(0)false false true true false str('text')int(0)false false true true false str('true')int(0)false false true true false int(1)str('01')false false true true true false int(1)str('1')false false true true true false str('1')str('01')false false true true false
同时降低和更大?
$ a VS. $ b $ a> $ b $ a <$ b $ a <= $ b $ a> = $ b $ a == $ b $ a === $ b float(NAN)str(“\ 0”)true true true true false false float(NAN)str('')true true true true false false float(NAN)str('+')true true true true false false float(NAN)str(' - ')true true true true false false float(NAN)str('0')true true true true false false float(NAN)str('01')true true true true false false float(NAN)str('1')true true true true false false float(NAN)str('false')true true true true false false float(NAN)str('text')true true true true false false float(NAN)str('true')true true true true false false
相同和相同:
$ a VS. $ b $ a> $ b $ a <$ b $ a <= $ b $ a> = $ b $ a == $ b $ a === $ b NULL(NULL)NULL(NULL)false false true true true float(-INF)float(-INF)false false true true true float(INF)float(INF)false false true true true
更低或更高:
$ a VS. $ b $ a> $ b $ a <$ b $ a <= $ b $ a> = $ b $ a == $ b $ a === $ b
NULL(NULL)bool(true)false true true false false float(-INF)NULL(NULL)true false false true false false NULL(NULL)float(1)false true true false false float(INF)NULL(NULL)true false false true false false float(NAN)NULL(NULL)true false false false false NULL(NULL)int(-1)false true true false false NULL(NULL)int(1)false true true false false NULL(NULL)str(“\ 0”)false true true false false NULL(NULL)str('+')false true true false false NULL(NULL)str(' - ')false true true false false NULL(NULL)str('0')false true true false false NULL(NULL)str('01')false true true false false NULL(NULL)str('1')false true true false false NULL(NULL)str('false')false true true false false NULL(NULL)str('text')false true true false false NULL(NULL)str('true')false true true false false array()bool(true)false true true false false float(-INF)数组()false false true false false false array()float(0)true false false true false array()float(1)true false false true false float(INF)array()false true true false false float(NAN)array()false true true false false array()int(-1)true false false true false array()int(0)true false false true false array()int(1)true false false true false array()str(“\ 0”)true false false true false false str('')array()false true true false false array()str('+')true false false true false false array()str(' - ')true false false true false array()str('0')true false false false false array()str('01')true false false true false array()str('1')true false false false false array()str('false')true false false true false array()str('text')true false false false false array()str('true')true false false false false bool(true)bool(false)true false false true false false float(-INF)bool(false)true false false true false false float(1)bool(false)true false false true false false float(INF)bool(false)true false false true false false float(NAN)bool(false)true false false true false false bool(false)int(-1)false true true false false false int(1)bool(false)true false false true false false bool(false)str(“\ 0”)false true true false false bool(false)str('+')false true true false false false bool(false)str(' - ')false true true false false bool(false)str('01')false true true false false false str('1')bool(false)true false false true false false bool(false)str('false')false true true false false false str('text')bool(false)true false false false false str('true')bool(false)true false false false false bool(true)float(0)true false false true false bool(true)int(0)true false false true false str('')bool(true)false true true false false bool(true)str('0')true false false true false false float(-INF)float(0)false true true false false float(-INF)float(1)false true true false false float(INF)float(-INF)true false false true false false float(-INF)int(-1)false true true false false float(-INF)int(0)false true true false false float(-INF)int(1)false true true false false float(-INF)str(“\ 0”)false true true false false float(-INF)str('')false true true false false float(-INF)str('+')false true true false false float(-INF)str(' - ')false true true false false float(-INF)str('0')false true true false false float(-INF)str('01')false true true false false float(-INF)str('1')false true true false false float(-INF)str('false')false true true false false float(-INF)str('text')false true true false false float(-INF)str('true')false true true false false float(1)float(0)true false false true false float(INF)float(0)true false false true false float(0)int(-1)true false false true false int(1)float(0)true false false true false float(0)str('01')false true true false false str('1')float(0)true false false true false float(INF)float(1)true false false true false false float(1)int(-1)true false false true false float(1)int(0)true false false true false float(1)str(“\ 0”)true false false true false false str('')float(1)false true true false false float(1)str('+')true false false true false float(1)str(' - ')true false false true false float(1)str('0')true false false true false float(1)str('false')true false false true false false str('text')float(1)false true true false false str('true')float(1)false true true false false float(INF)int(-1)true false false true false float(INF)int(0)true false false true false float(INF)int(1)true false false true false false float(INF)str(“\ 0”)true false false true false false float(INF)str('')true false false false false float(INF)str('+')true false false true false false float(INF)str(' - ')true false false true false false float(INF)str('0')true false false true false false float(INF)str('01')true false false true false false float(INF)str('1')true false false true false false float(INF)str('false')true false false true false false float(INF)str('text')true false false true false false float(INF)str('true')true false false false false int(0)int(-1)true false false true false int(1)int(-1)true false false true false str(“\ 0”)int(-1)true false false true false str('')int(-1)true false false true false str('+')int(-1)true false false true false str(' - ')int(-1)true false false true false str('0')int(-1)true false false true false int(-1)str('01')false true true false false str('1')int(-1)true false false true false str('false')int(-1)true false false true false str('text')int(-1)true false false true false str('true')int(-1)true false false true false int(1)int(0)true false false true false int(0)str('01')false true true false false str('1')int(0)true false false true false int(1)str(“\ 0”)true false false true false false str('')int(1)false true true false false int(1)str('+')true false false true false false int(1)str(' - ')true false false true false int(1)str('0')true false false true false int(1)str('false')真假假真真假假 str('text')int(1)false true true false false str('true')int(1)false true true false false str('')str(“\ 0”)false true true false false str('+')str(“\ 0”)true false false true false false str(' - ')str(“\ 0”)true false false true false false str(“\ 0”)str('0')false true true false false str(“\ 0”)str('01')false true true false false str('1')str(“\ 0”)true false false true false false str('false')str(“\ 0”)true false false true false false str('text')str(“\ 0”)true false false true false false str('true')str(“\ 0”)true false false true false false str('')str('+')false true true false false str('')str(' - ')false true true false false str('')str('0')false true true false false str('')str('01')false true true false false str('')str('1')false true true false false false str('')str('false')false true true false false str('')str('text')false true true false false str('')str('true')false true true false false str(' - ')str('+')true false false true false str('+')str('0')false true true false false false str('+')str('01')false true true false false str('1')str('+')true false false true false false str('false')str('+')true false false true false false str('text')str('+')true false false true false false str('true')str('+')true false false true false false str(' - ')str('0')false true true false false str(' - ')str('01')false true true false false str('1')str(' - ')true false false true false false str('false')str(' - ')true false false true false false str('text')str(' - ')true false false true false false str('true')str(' - ')true false false true false false str('0')str('01')false true true false false str('1')str('0')true false false true false false str('false')str('0')true false false true false false str('text')str('0')true false false true false false str('true')str('0')true false false true false false str('false')str('01')true false false true false false str('text')str('01')true false false true false str('true')str('01')true false false true false false str('1')str('false')false true true false false str('text')str('1')true false false true false false str('true')str('1')true false false true false false str('text')str('false')true false false true false false str('true')str('false')true false false true false false str('true')str('text')true false false false false
$a > $b > $c
当以下情况$a
时: $a
不大于$c
。
A&ltC:float(NAN)> str('a')> str('') A&ltC:float(NAN)> str('a')> str('1') A&ltC:float(NAN)> str('a')> str('A') A&ltC:float(NAN)> str('a')> str('0') A&ltC:float(NAN)> str('1')> str('') A&ltC:float(NAN)> str('1')> str('0') A&ltC:float(NAN)> str('A')> str('') A&ltC:float(NAN)> str('A')> str('1') A&ltC:float(NAN)> str('A')> str('0') A&ltC:float(NAN)> str('0')> str('') A&ltC:str('')> float(NAN)> str('a') A&ltC:str('')> float(NAN)> str('1') A&ltC:str('')> float(NAN)> str('A') A&ltC:str('')> float(NAN)> str('0') A&ltC:str('a')> str('')> float(NAN) A&ltC:str('a')> str('1')> float(NAN) A&ltC:str('a')> str('A')> float(NAN) A&ltC:str('a')> str('0')> float(NAN) A&ltC:str('0')> str('')> float(NAN) A == C:bool(true)> str('')> float(NAN) A == C:bool(true)> str('')> float(-INF) A == C:bool(true)> str('')> int(-1) A == C:bool(true)> str('')> float(-1) A == C:bool(true)> array()> float(NAN) A == C:bool(true)> array()> float(INF) A == C:bool(true)> array()> float(-INF) A == C:bool(true)> array()> str('a') A == C:bool(true)> array()> int(1) A == C:bool(true)> array()> float(1) A == C:bool(true)> array()> str('1') A == C:bool(true)> array()> str('A') A == C:bool(true)> array()> int(-1) A == C:bool(true)> array()> float(-1) A == C:bool(true)> int(0)> float(-INF) A == C:bool(true)> int(0)> int(-1) A == C:bool(true)> int(0)> float(-1) A == C:bool(true)> str('0')> float(NAN) A == C:bool(true)> str('0')> float(-INF) A == C:bool(true)> str('0')> int(-1) A == C:bool(true)> str('0')> float(-1) A == C:bool(true)> float(0)> float(-INF) A == C:bool(true)> float(0)> int(-1) A == C:bool(true)> float(0)> float(-1) A == C:int(1)> str('a')> str('1') A == C:int(1)> str('A')> str('1') A == C:float(1)> str('a')> str('1') A == C:float(1)> str('A')> str('1') A == C:str('a')> str('1')> int(0) A == C:str('a')> str('1')> float(0) A == C:str('')> float(-INF)> NULL(NULL) A == C:str('')> float(-INF)> bool(false) A == C:str('')> int(-1)> NULL(NULL) A == C:str('')> int(-1)> bool(false) A == C:str('')> float(-1)> NULL(NULL) A == C:str('')> float(-1)> bool(false) A == C:array()> float(NAN)> NULL(NULL) A == C:array()> float(NAN)> bool(false) A == C:array()> float(INF)> NULL(NULL) A == C:array()> float(INF)> bool(false) A == C:array()> float(-INF)> NULL(NULL) A == C:array()> float(-INF)> bool(false) A == C:array()> str('a')> NULL(NULL) A == C:array()> str('a')> bool(false) A == C:array()> int(1)> NULL(NULL) A == C:array()> int(1)> bool(false) A == C:array()> float(1)> NULL(NULL) A == C:array()> float(1)> bool(false) A == C:array()> str('1')> NULL(NULL) A == C:array()> str('1')> bool(false) A == C:array()> str('A')> NULL(NULL) A == C:array()> str('A')> bool(false) A == C:array()> str('0')> NULL(NULL) A == C:array()> int(-1)> NULL(NULL) A == C:array()> int(-1)> bool(false) A == C:array()> float(-1)> NULL(NULL) A == C:array()> float(-1)> bool(false) A == C:str('')> float(NAN)> bool(false) A == C:str('')> float(NAN)> NULL(NULL) A == C:str('A')> str('1')> int(0) A == C:str('A')> str('1')> float(0) A == C:int(0)> float(-INF)> NULL(NULL) A == C:int(0)> float(-INF)> bool(false) A == C:int(0)> int(-1)> NULL(NULL) A == C:int(0)> int(-1)> bool(false) A == C:int(0)> float(-1)> NULL(NULL) A == C:int(0)> float(-1)> bool(false) A == C:str('0')> float(NAN)> bool(false) A == C:str('0')> float(-INF)> bool(false) A == C:str('0')> int(-1)> bool(false) A == C:str('0')> float(-1)> bool(false) A == C:float(0)> float(-INF)> NULL(NULL) A == C:float(0)> float(-INF)> bool(false) A == C:float(0)> int(-1)> NULL(NULL) A == C:float(0)> int(-1)> bool(false) A == C:float(0)> float(-1)> NULL(NULL) A == C:float(0)> float(-1)> bool(false) A === C:str('0')> float(NAN)> str('0') A === C:str('')> float(NAN)> str('') A === C:str('a')> float(NAN)> str('a') A === C:str('1')> float(NAN)> str('1') A === C:str('A')> float(NAN)> str('A')
有趣的string比较:“女王” >
“国王” >
“杰克” >
“王牌”
另外检查一下PHPtypes比较表,包括对:
-
isset()
和is_null()
-
if()
和empty()
- 布尔
==
与===
检查PHP版本之间的差异。 http://3v4l.org/MAfDu 。
在你对问题的第二部分进行修改之后,我将这一部分的答案留给其他人。 我只想给你的问题的第一部分提供最令人惊讶的答案,即是否存在一个<
和>
操作符不灵敏的例子。 这里是。
这些都是true
:
"10" < "1a" "1a" < "2" "10" > "2"
如果<
传递( $a < $b
^ $b < $c
$a < $c
),最后一行是
"10" < "2"
但是PHP会尽可能的善良(?!),并且尽可能的将string解释为数字。
事实certificate,由于上述不可行性, 即使没有两个元素==
(且没有元素是NAN), sort()
也可以根据它们的input顺序将相同的元素sorting为不同的顺序。 我在对sort()的评论中指出这一点,其实质是:
sort(array("10", "1a", "2" )) => array("10", "1a", "2" ) sort(array("10", "2", "1a")) => array("1a", "2", "10") sort(array("1a", "10", "2" )) => array("2", "10", "1a") sort(array("1a", "2", "10")) => array("1a", "2", "10") sort(array("2", "10", "1a")) => array("2", "10", "1a") sort(array("2", "1a", "10")) => array("10", "1a", "2" )