我遇到过这段代码
<?php
$a = md5('240610708');
$b = md5('QNKCDZO');
echo "$a\n";
echo "$b\n";
echo "\n";
var_dump($a);
var_dump($b);
var_dump($a == $b);
这将评估2个字符串,可以是数字0exxxxxx
。我理解,如果在数字上下文中使用任何一个,那么该字符串将被视为一个数字,由http://www.php.net/manual/en/language.types.string.php#language.types.string.conversion确认
在数值上下文中计算字符串时,结果值 和类型确定如下。
如果字符串不包含任何字符'。','e'或'E' 并且数值适合整数类型限制(由...定义) PHP_INT_MAX),该字符串将被计算为整数。在所有其他 案例将被评估为浮动。
该值由字符串的初始部分给出。如果是字符串 从有效的数字数据开始,这将是使用的值。 否则,该值将为0(零)。有效的数字数据是 可选符号,后跟一个或多个数字(可选地包含一个 小数点),后跟可选的指数。指数是一个 'e'或'E'后跟一个或多个数字。
我只是不确定为什么==
在双方都是string类型时触发数字比较。
答案 0 :(得分:5)
这是PHP中字符串“智能”比较的结果。是的,这不是你所期望的,但是现在 - 它是如何实现的。
维持比较
要实现这一点的原因,您需要查看PHP源代码(更好或更好)。在PHP中,有compare_function
这样的东西用于处理比较。它包含不同类型参数的不同情况。因此,对于字符串,它是:
case TYPE_PAIR(IS_STRING, IS_STRING):
zendi_smart_strcmp(result, op1, op2);
return SUCCESS;
TYPE_PAIR
和任何其他东西一样只是一个宏。
更深入
从上一步开始,我们现在转移到zendi_smart_strcmp
。比较两个字符串是PHP的“聪明之物”。我们在这里:
if ((ret1=is_numeric_string_ex(Z_STRVAL_P(s1), Z_STRLEN_P(s1), &lval1, &dval1, 0, &oflow1)) && (ret2=is_numeric_string_ex(Z_STRVAL_P(s2), Z_STRLEN_P(s2), &lval2, &dval2, 0, &oflow2)))
{
//compare as two numbers, I've omitted this
}
else
{
string_cmp: //yes, yes, we're using goto
Z_LVAL_P(result) = zend_binary_zval_strcmp(s1, s2);
ZVAL_LONG(result, ZEND_NORMALIZE_BOOL(Z_LVAL_P(result)));
}
在省略的代码中,还有一部分用于确定结果是long
还是double
- 但这是无关紧要的,因为我们已经知道什么导致比较为浮点数:只要字符串可以被视为数字,PHP将使用它来产生比较 - 和 - 是的,意图(所以,是的,字符串"1000"
相等到"1e3"
使用==
运算符时,"255"
和"0xFF"
运算符相同 - 它们不包含“e”(指数)部分,但仍然相等)
您可以使用例如:
来限制案例var_dump("0e8" == "0e6"); //true
所以不需要处理md5哈希。如果将其作为数字进行比较,则为真(因为两个操作数都是有效的浮点数,0 x 10^8
== 0 x 10^6
)。但它们与字符串不同。因此,您的直接解决方案是 - 使用===
运算符进行比较:
var_dump("0e8" === "0e6"); //false
是的,这在PHP中是一个令人困惑的事情 - 因为它并不明显(至少有争议)。但这就是它目前的工作方式。