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

标签 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); 

这会评估 2 个可能是数字 0exxxxxx 的字符串。我知道如果在数字上下文中使用其中任何一个,那么字符串将被视为数字,正如 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.

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

最佳答案

长话短说

这是 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 - 但这是无关紧要的,因为我们已经知道是什么原因导致了 float 的比较:as long由于字符串可以被视为数字,PHP 将使用它来进行比较 - 并且 - 是的,这是有意的(所以,是的,字符串 "1000"当使用 == 运算符时, 等于 "1e3",同样适用于 "255""0xFF" - 它们不包含“e”(指数)部分,但仍然相等)

解决方案

您可以限制大小写,例如:

var_dump("0e8" == "0e6"); //true

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

var_dump("0e8" === "0e6"); //false

是的,这在 PHP 中是一件令人困惑的事情——因为它并不明显(至少值得商榷)。但这就是它目前的工作方式。

关于php 字符串比较,为什么转换为 float ,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/23755926/

相关文章:

javascript - 尽管刷新,jQuery 格式仍不适用于 ajax 数据

java - 读取.txt文档并在Java中进行编辑时出现问题

string - 批量匹配一个变量到另一个变量的一部分

php - 在 PHP 文件中向 MySQL 数据库发出隐藏密码

php - Yii2 多对多关系的订单项

javascript - 如何从 Javascript 日期中获取年份的最后 2 位数字

JavaScript - 使用数组检查字符串

c - 在 C 中创建获取字符串函数时遇到问题

PHP 检查时间是否在两次之间而不考虑日期

php - Facebook API : Login using JavaScript SDK then checking login state with PHP