比较操作符,如<
、>
和==
,可以根据比较对象返回1或0(或空),使得PHP根据其返回值来做出决定。看一下下面的代码:
<?php
if ($foo < 10) {
// do stuff
}
?>
小于操作符<
将$foo
同10进行比较,如果$foo
小于10,则返回1使得第一行代码成为if(1) {
。之前说过,PHP将0或空视为false
,其他的值视为true
,也就是说,那行代码相当于if(true) {
。自然,true
就意味着后面的代码块可以执行。
知道了比较操作符是怎么操作的,你就应该能够通过范围检查避免一些常识性的错误。来看一下下面的代码:
<?php
if ($a <= $b <= $c) {
// do stuff
}
?>
这里,我们好像是想要$b
大于等于$a
,同时要小于等于$c
,但是实际情况不是这样的!PHP首先会比较$a
和$b
的大小,返回0或1,然后再用0或1同$c
进行大小比较——这明显不是我们想要的,可以将上述代码重写为:
<?php
if ($a <= $b && $b <= $c) {
// do stuff
}
?>
在修改版中,我们将两个分别进行检查,相对来说会好一点。
接下来,我们要问一下你,等号==
的作用是什么?如果你的回答是“你连这个都不知道吗?两个值相等的时候返回真啊”的话,你就和大多数人一样了。
来看一下这个代码:
if (31415926535897932 == 31415926535897933) {
echo "Numbers are the same!\n";
} else {
echo "Numbers are not the same!\n";
}
不用费劲去数两个数字了:第一个是π取17位数,第二个是π取17位数加1。两个数都把小数点去掉了。想一想,上面的代码会输出什么。提示一点:这个问题有点坏!
在阅读答案之前,我强烈建议你们在PHP中运行一下,这样可能解释起来更加容易一些。
尽管两个数不一样,PHP还是会输出“Numbers are the same!”。这是因为PHP对大数的支持不好,当超过一个特定的数值的时候,用==
来判断数字相等就不靠谱了。
在内部,PHP默认使用整型(int)来存储数字。当你用一个很大的整型加上另一个很大的整型,PHP知道结果超过整型的范围,就会将结果保存成浮点型(float)。浮点型的数一般都很大,当超过16位数字时,PHP会舍弃掉后面的部分。
下面这段代码简单的阐释了一下:
$foo = 2147483647;
var_dump($foo);
++$foo;
var_dump($foo);
$bar = 31415926535897932;
$baz = 31415926535897933;
var_dump($bar);
var_dump($baz);
上面的代码输出为:
int(2147483647)
float(2147483648)
float(31415926535898000)
float(31415926535898000)
上面第一个数字是整型的,加一之后超过了整型的范围,PHP将其转换为浮点型。再看一下后面两个数字,都是浮点型,默认精度是14位数字,所以前面的部分都成了31415926535898。所以在进行大数比较的时候,结果通常都是相等。
有两种解决方案,但是两种都不完美。第一种,你可以将两个数字作为字符串进行比较。PHP进行字符串比较的时候是逐字进行比较字符的大小的,因此可以比较数字的大小。但是,这并不是简单的用双引号将数字引起来就可以解决的问题。PHP是一种弱类型语言,字符串里面都是数字的时候将会自动将其转换为整型,因此还会出现相同的问题。
这里的解决方案是将等号换为绝对等号===
,用来比较两个值是不是相等且同类型。所以,如果我们用引号将数字引起来将其变为字符串,再用===
进行比较,PHP为了确保类型相同就不会自动将其转换为整型了。这样,才会将两个数字作为字符串进行比较,得到我们想要的结果。下面是代码:
if ("31415926535897932" === "31415926535897933") {
echo "Numbers are the same!\n";
} else {
echo "Numbers are not the same!\n";
}
Delbert说明:经过本人在5.3.29版本的PHP当中测试,确实是存在这样的问题,但是在5.5.9版中已经不存在这样的问题了。(未测试更老版本)
var_dump
的结果如下:int(2147483647) int(2147483648) int(31415926535897932) int(31415926535897933)
直接测试输出的是“Numbers are not the same!”。