2018-09-18
参考文献:
Darry_Zhao: PHP数字与字符串比较的误区
今天工作中发现提供的订单查询接口有bug
编写时认为当
- 需要下载时,查询条件中的
$is_download=1
- 不需要下载时,不传
$is_download
或$is_download=0
但是对方是这样处理: $is_download="download"
和 不传
结果导致 $download==0
成立,从而进入了错误的分支
搜索后发现
将一个无法转换为数字的字符串转化为数字,结果总是为0 ,所以将其与0总是返回true。
处理方式
使用强类型判断
延伸阅读
PHP中比较运算符的规则
- 当两个字符进行比较时,比较这两个字符的ASCII码
- 当两个字符串进行比较时,从第一个字符开始挨个比较对应的ASCII码,知道某一位置两个字符ASCII码不一致时给出结果,如'ba'>'az','10'<'a'
- 当一个数字与一个字符/字符串比较时,首先将字符/字符串转化为数字,再与数字进行比较,如12<'21as', 'dsa'=0,同理 'a'+10=10;
- 当两个数字字符串进行比较时,首先将两个字符串当做数字,并且用科学计数法存储这两个字符串,科学计数法保留小数点后16位,再进行比较。
由此就会产生一个bug
如:
$str1 = "123456789012345678";
$str2 = "123456789012345679";
(最后一位不一样)
在比较时会先将两个字符串用科学计数法进行储存,因为保留16位小数,所以结果为
$str1=1.2345678901234567E+17;
$str2=1.2345678901234567E+17。
结果再比较就会产生 $str1
等于 $str2
这样的结果;
解决办法为使用 ===
或者 strcmp
等字符串比较函数进行强类型判断
另外,长度不同、在字符串中加非数字字符等等都会引起两个字符串的不等。例如:
$str1 = "a123456789012345678";
$str2 = "a123456789012345679";
此时 $str1
和 $str2
就不相等,因为存在 a
这个非数字字符,所以系统不会讲两个字符串当成数字字符串进行比较,而是使用 2.
中两个字符串比较方法。