php字符串比较,为什么要转换为float

exu*_*sum 4 php string

我遇到过这段代码

<?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); 
Run Code Online (Sandbox Code Playgroud)

这将评估2个可能是数字的字符串0exxxxxx.据我所知,如果在数字上下文中使用任何一个,那么该字符串将被视为一个数字,如http://www.php.net/manual/en/language.types.string.php#language.types所证实. string.conversion

在数值上下文中计算字符串时,结果值和类型将按如下方式确定.

如果字符串不包含任何字符'.','e'或'E',并且数值适合整数类型限制(由PHP_INT_MAX定义),则字符串将被计算为整数.在所有其他情况下,它将被评估为浮点数.

该值由字符串的初始部分给出.如果字符串以有效数字数据开头,则这将是使用的值.否则,该值将为0(零).有效数字数据是可选符号,后跟一个或多个数字(可选地包含小数点),后跟可选指数.指数是'e'或'E',后跟一个或多个数字.

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

Alm*_* Do 5

TL; DR

这是PHP中字符串"智能"比较的结果.是的,它不是你所期望的,但是现在 - 它是如何实现的.

深层发掘

保持比较

为了实现这个原因,你需要研究PHP源代码(更好或更好).在PHP中,有一些compare_function用于处理比较的东西.它包含不同类型参数的不同情况.所以,对于字符串,它是:

case TYPE_PAIR(IS_STRING, IS_STRING):
    zendi_smart_strcmp(result, op1, op2);
    return SUCCESS;
Run Code Online (Sandbox Code Playgroud)

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)));
}
Run Code Online (Sandbox Code Playgroud)

在省略的代码中还有一部分用于确定结果是否longdouble- 但这是无关紧要的,因为我们已经知道是什么导致比较为浮点数:只要字符串可以被视为数字,PHP将使用它来产生比较 - 和 - 是,即预期(所以,是的,字符串"1000"等于"1e3"使用的时候==操作,同为"255""0xFF"-它们不包含"E"(指数)的一部分,但仍然是平等的)

例如,您可以限制案例:

var_dump("0e8" == "0e6"); //true
Run Code Online (Sandbox Code Playgroud)

所以不需要处理md5哈希.如果将其作为数字进行比较,则为真(因为两个操作数都是有效的浮点数,而且0 x 10^8== 0 x 10^6).但它们与字符串不同.因此,您的直接解决方案是 - 使用===运算符进行比较:

var_dump("0e8" === "0e6"); //false
Run Code Online (Sandbox Code Playgroud)

是的,这在PHP中是一个令人困惑的事情 - 因为它并不明显(至少有争议).但这就是目前的工作方式.