Понимание приведения типов PHP

Я увидел этот небольшой фрагмент кода, который ускользает от моего понимания:

<?php

$a = '0e462097431906509019562988736854';
$b = '0e830400451993494058024219903391';

var_dump($a == $b);

Что выведет:

bool(true)

Я понимаю, что при использовании == PHP попытается выполнить нечеткое сравнение, автоматически конвертируя типы для выполнения сравнения. Чего я не понимаю, так это почему PHP считает эти две строки одинаковыми. Я бы подумал, что поскольку $a и $b являются строками, преобразование типов не требуется.

Что я не понимаю?


person amphetamachine    schedule 04.11.2014    source источник


Ответы (4)


Я думаю, что эта статья объясняет это довольно хорошо:

Операторы сравнения с приведением типов преобразуют числовые строки в числа

Просто процитирую основную проблему здесь:

Согласно php language.operators.comparison, операторы сравнения с приведением типов приведут оба операнда к плавает, если они оба выглядят как числа, даже если они оба уже являются строками:

где обе строки используют экспоненциальное представление, следовательно, обрабатываются как числовые строки, делая свободное сравнение (==), приведите эти строки к числам с плавающей запятой, прежде чем фактически грубо их сравнивая.

В качестве наилучшей практики и для предотвращения неожиданного поведения всегда старайтесь использовать равенство удостоверений. (===), особенно при работе с строками.

person Kypros    schedule 04.11.2014

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)
person Brandon Johnson    schedule 04.11.2014

Это не совсем ответ, но если вы попробуете

$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 преобразует строки в числа с плавающей запятой и дает результат сравнения, используя полученные числа с плавающей запятой, которые в любом случае неверны, но это уже другая история.

person M. Page    schedule 04.11.2014
comment
Но почему, когда оба являются строками? - person amphetamachine; 04.11.2014

В официальной документации проверка равенства между двумя переменными выполняется следующим образом:

$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 :)
person Halayem Anis    schedule 04.11.2014