理解PHP类型强制


Understanding PHP type coercion

我看到了一小段逃避我理解的代码:

<?php
$a = '0e462097431906509019562988736854';
$b = '0e830400451993494058024219903391';
var_dump($a == $b);

将输出:

bool(true)

我知道当使用==时,PHP会尝试模糊比较,在类型之间无声地转换以执行比较。我所不理解的是为什么PHP似乎认为这两个字符串是相同的。我本以为$a$b是字符串,所以不需要进行类型转换。

我有什么不明白的?

我认为这篇文章很好地解释了它:

类型强制比较运算符将数字字符串转换为数字

这里只引用主要问题:

根据php language.operators.comparsion,如果两个操作数看起来都像数字,即使它们都已经是字符串,类型强制比较运算符也会强制两个操作符为浮点:

其中两个字符串都使用指数表示法,因此被视为数字字符串,进行松散比较(==),在实际";松散地";比较它们。

作为最佳实践,为了防止意外行为,请始终尝试使用身份平等(===),,尤其是在处理字符串时。

PHP试图转换为float类型,因为字符串以0开头。它在0之后停止,因为下一个字符不是数字。当您使用类型强制将科学表示法转换为整数时,也会发生同样的情况:

$x = (float)"12E-1x";  // $x == 1.2
$x = (int)"12E-1x";  // $x == 12 (stops at E because it's not an integer)

这不是一个真正的答案,但如果你尝试

$a = '0e4620974319065090195629887368549';
$b = '0e8304004519934940580242199033918';
echo floatval($a) . '<br>' . floatval($b);var_dump($a == $b);

你得到:

0
0
bool(true)

现在,如果你尝试:

$a = '0e4620974319065090195629887368549';
$b = '1e8304004519934940580242199033918';
echo floatval($a) . '<br>' . floatval($b);var_dump($a == $b);

你得到:

0
INF
bool(false)

我的猜测是,PHP将字符串转换为浮点值,并使用获得的浮点值给出比较结果,这无论如何都是不正确的,但这是另一回事。

在官方文档中,两个变量之间的相等性测试如下:

$a == $b # Equal TRUE if $a is equal to $b after type juggling.

示例

$a = 13;   # Integer type
$b = "13"; # String type
var_dump($a == $b); # Will say TRUE, because juggling was made
var_dump($a === $b); # Will say FALSE, because PHP will also evaluate the type of variables :)