2014-05-20 29 views
4

香港专业教育学院碰到过这样的代码PHP的字符串比较,为什么投浮

<?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'后跟一个或多个数字。

我只是不确定为什么==当双方都是字符串类型时触发数值比较。

+1

@Hanky웃Panky在意识到'==='但是当双方都是字符串时,什么导致双方被当作浮动。我知道这发生在有多种类型时 – exussum

回答

5

TL; DR

这是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))); 
} 

里面省略码也有用于确定结果是longdouble部分 - 但是这无关紧要,因为我们已经知道是什么引起的比较,因为花车:只要字符串可以治疗数字,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中令人困惑的事情 - 因为它并不明显(和有争议至少)。但这就是目前的工作原理。