Сравнение строки с целым числом дает странные результаты

Я действительно смущен тем, почему эта операция работает. Может ли кто-нибудь объяснить это?

$test1 = "d85d1d81b25614a3504a3d5601a9cb2e";
$test2 = "3581169b064f71be1630b321d3ca318f";

if ($test1 == 0)
  echo "Test 1 is Equal!?";
if ($test2 == 0)
  echo "Test 2 is Equal!?";

// Returns: Test 1 is Equal!?

Для пояснения, я пытаюсь сравнить строку "0" с переменными $test. Я уже знаю, как исправить код, который я могу просто заключить (как и следовало) 0 в ""s

Мне интересно, является ли это ошибкой PHP, ошибкой сервера или каким-то образом допустимой операцией. Согласно http://us3.php.net/types.comparisons это не должно сработало.

Редактировать: Сотрите это, по-видимому, в нем упоминается, что свободные сравнения между строкой и 0 верны. Но я до сих пор не знаю, почему.

Редактировать 2: я пересмотрел свой вопрос, почему значение $test2 для "3581169b064f71be1630b321d3ca318f" не работает?


person St. John Johnson    schedule 23.03.2009    source источник
comment
какое значение $test не работает?   -  person Assaf Lavie    schedule 23.03.2009
comment
Если вы запустите код, он выводит только Test 1 is Equal!?   -  person St. John Johnson    schedule 23.03.2009
comment
Редактировать 2: потому что оператор сравнения автоматически приводит 3581169b064f71be1630b321d3ca318f и, поскольку он начинается с чисел, он преобразуется в int и получает первую часть строки до буквы в качестве значения. и это сравнение (3581169 == 0) с ложным   -  person Erdinç Çorbacı    schedule 27.10.2019
comment
FWIW, печать значений $test1 + 0 и $test2 + 0 дала бы ключ к пониманию того, что происходит. Или, альтернативно, значения +$test1 и +$test2 (с использованием оператора идентификации).   -  person ToolmakerSteve    schedule 14.08.2020


Ответы (5)


Из руководства по PHP:

Преобразование строк в числа

Когда строка оценивается в числовом контексте, результирующее значение и тип определяются следующим образом.

Строка будет оцениваться как число с плавающей запятой, если она содержит любой из символов '.', 'e' или 'E'. В противном случае он будет оцениваться как целое число.

Значение задается начальной частью строки. Если строка начинается с допустимых числовых данных, это будет используемое значение. В противном случае значение будет равно 0 (ноль). Допустимые числовые данные — это необязательный знак, за которым следует одна или несколько цифр (необязательно содержащая десятичную точку), за которыми следует необязательный показатель степени. Показатель степени представляет собой букву «e» или «E», за которой следует одна или несколько цифр.

person Assaf Lavie    schedule 23.03.2009
comment
Тем не менее, не думайте, что он должен преобразовываться в 0 или, по крайней мере, если он начинается с числа, чтобы не преобразовывать его в десятичное число, если в строке есть ошибочные символы. - person St. John Johnson; 23.03.2009
comment
PHP не имеет типа NaN, такого как Javascript (еще один язык со свободной типизацией), поэтому он в значительной степени должен преобразовываться в 0, поскольку другого пути не было бы (преобразование в NULL не сработает, потому что NULL также преобразуется в 0). Я думаю, что ответ не в том, чтобы использовать свободное сравнение (==) или сначала проверять строку. - person thomasrutter; 23.03.2009
comment
В дополнение к этому ответу при сравнении двух элементов с помощью оператора == он преобразуется в общий тип. это упоминается здесь. php.net/manual/en/language.operators.comparison.php< /а> - person Nis; 26.03.2014
comment
Лучший способ выполнить тест — использовать пустой метод: empty($test1) - person Pascal_dher; 21.01.2015
comment
@Pascal_dher - тьфу, нет. Причина: скажите, что вы имеете в виду. Здесь цель состоит в том, чтобы задать вопрос равно ли это значение 0. Выражение, похожее на намерение, является очевидным, тогда как выражение, основанное на причуде языка, является неочевидным. ПО МОЕМУ МНЕНИЮ. [Если бы единственным существующим компьютерным языком был PHP, тогда ваше предложение было бы разумным. Однако это все равно не сделало бы его наилучшим способом; это просто сделало бы его равноценно хорошей альтернативой.] - person ToolmakerSteve; 14.08.2020

Преобразование типов с помощью оператора ==

Оператор == представляет собой сравнение со свободной типизацией. Он преобразует оба в общий тип и сравнит их. Способ преобразования строк в целые объяснен здесь.

Обратите внимание, что страница, на которую вы ссылаетесь, этому не противоречит. Проверьте вторую таблицу, где сказано, что сравнение целого числа 0 со строкой "php" с использованием == должно быть верным.

Что происходит, так это то, что строка преобразуется в целое число, а нечисловые строки (строки, которые не содержат числа или не начинаются с числа) преобразуются в 0.

Числовые и нечисловые строки

Строка, состоящая из числа или начинающаяся с числа, считается числовой строкой. Если в строке есть другие символы после этого числа, они игнорируются.

Если строка начинается с символа, который не может быть интерпретирован как часть числа, то это нечисловая строка, и она будет преобразована в 0. Это не означает, что числовая строка должна начинаться с цифры (0-9) — например, "-1" — это числовая строка, поскольку в этом случае знак минус является частью числа.

Так, например, ваша строка "d85d1d81b25614a3504a3d5601a9cb2e" не начинается с цифры, поэтому она будет преобразована в 0. Но ваша вторая строка "3581169b064f71be1630b321d3ca318f" будет преобразована в целое число 3581169. Вот почему ваш второй тест не работает так же.

Что следует делать

Вы, вероятно, хотите:

if ($test1 === "0")

Обратите внимание на использование тройного равенства вместо двойного равенства. Это гарантирует, что вы сравниваете строку, содержащую только цифру ноль, и предотвращает любое преобразование типов.

person thomasrutter    schedule 23.03.2009

После некоторого расследования выясняется, что Эйдан из руководства по PHP упомянул, что любые строки, которые не начинаются с цифры, будут преобразованы в 0 при преобразовании в целое число.

Это означает, что:

("php" == 0) === true
("1php" == 0) === false

Очень раздражает и плохо документирован. Это было внизу комментариев на странице сравнения типов.

person St. John Johnson    schedule 23.03.2009
comment
Да, понял, что это было. Плохая документация действительно. - person Paolo Bergantino; 23.03.2009
comment
Я вовсе не думаю, что это плохая документация. Неявное преобразование типов — это основа PHP, которая очень хорошо объясняется в руководстве в разделе «Типы», особенно в разделе «Жонглирование типами». == — это сравнение с нестрогим типом; использование === вместо этого может помочь предотвратить запутанные ситуации. - person thomasrutter; 23.03.2009
comment
См. также Преобразование строк в числа по адресу us3. .php.net/manual/ru/ - person thomasrutter; 23.03.2009

$test1 = "d85d1d81b25614a3504a3d5601a9cb2e";

эта строка начинается с «d», что не является допустимым числом, переменная будет преобразована в 0, и ваш тест № 1 будет пройден.

$test2 = "3581169b064f71be1630b321d3ca318f";

эта строка начинается с 3581169, что является допустимым числом, поэтому переменная будет разрешаться в это значение, которое не равно 0. Таким образом, ваш тест № 2 не будет пройден.

person HBR    schedule 06.08.2014

Я использовал некоторые преобразования и сравнения, чтобы проверить, является ли числовая строка числом:

$test1="19de6a91d2ca9d91721d82f1bd8102b6";
   echo (float)$test1==$test1; //TRUE
   echo is_float($test1); //FALSE

   //Converting the string to float and then converting it to string and compare will do the trick 
   echo (string)((float)$test1)==(string)$test1; //FALSE


$test2="5.66";
   echo (float)$test2==$test2; //TRUE

   //Testing the numeric string using `is_float` wont give the expected result
   echo is_float($test2); //FALSE

   echo (string)((float)$test2)==(string)$test2; //TRUE
person Eiad Samman    schedule 06.05.2014