我遇到过这段代码
<?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',后跟一个或多个数字。
我只是不确定为什么==当双方都是字符串类型时触发数字比较。
Ive come across this code
<?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);This evaluates that 2 strings which could be a number 0exxxxxx. I understand that if either are used in a numeric context then the string will be taken as a number, as confirmed by http://www.php.net/manual/en/language.types.string.php#language.types.string.conversion
When a string is evaluated in a numeric context, the resulting value and type are determined as follows.
If the string does not contain any of the characters '.', 'e', or 'E' and the numeric value fits into integer type limits (as defined by PHP_INT_MAX), the string will be evaluated as an integer. In all other cases it will be evaluated as a float.
The value is given by the initial portion of the string. If the string starts with valid numeric data, this will be the value used. Otherwise, the value will be 0 (zero). Valid numeric data is an optional sign, followed by one or more digits (optionally containing a decimal point), followed by an optional exponent. The exponent is an 'e' or 'E' followed by one or more digits.
Im just not sure why == triggers a numeric comparison when both sides are of type string.
最满意答案
TL; DR
这是PHP中字符串“智能”比较的结果。 是的,这不是你所期望的,但就目前而言 - 它是如何实现的。
深层发掘
保持比较
为了实现这个原因,你需要研究PHP源代码(更好或更好)。 在PHP中,有比较函数用于处理比较。 它包含不同类型参数的不同情况。 所以,对于字符串,它是:
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中是一个令人困惑的事情 - 因为它并不明显(至少有争议)。 但这就是目前的工作方式。
TL;DR
This is the result of "smart" comparison for strings in PHP. Yes, it is not what you can expect, but for now - it is how it's implemented.
Digging deeper
Maintaining comparison
To realize reason for this, you'll need to look into PHP sources (for greater good or bad). In PHP, there is such thing as compare_function which is used to handle comparisons. It contains different cases for different types of arguments. So, for strings it is:
case TYPE_PAIR(IS_STRING, IS_STRING): zendi_smart_strcmp(result, op1, op2); return SUCCESS;TYPE_PAIR, as any other stuff, is just a macro.
Moving deeper
From previous step, we're now moving to zendi_smart_strcmp. It is PHP's "smart thing" to compare two strings. And here we are:
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))); }Inside omitted code there is also part for determining if result is long or double - but that's irrelevant since we've already know what caused comparison as floats: as long as strings can be treated as numbers, PHP will use that to produce comparison - and - yes, that is intended (so, yes, string "1000" is equal to "1e3" when using == operator, same for "255" and "0xFF" - they don't contain "e" (exponent) part, but still are equal)
Solution
You may restrict the case with, for example:
var_dump("0e8" == "0e6"); //trueSo no need to deal with md5 hashes. If compare that as numbers, it's true (since both operands are valid floats, and 0 x 10^8 == 0 x 10^6). But they are not same as strings. Thus, your direct solution would be - use === operator to compare:
var_dump("0e8" === "0e6"); //falseYes, it's a confusing thing in PHP - because it is not obvious (and debatable at least). But that's how it currently works.
更多推荐
发布评论