Приведение типов и сравнение с Loose Operator "==" - PullRequest
7 голосов
/ 13 июля 2011

У меня есть проблема, ужасно сбивающая меня с толку.Я заметил это раньше, но до сегодняшнего дня не обращал на это внимания.Я пытался написать свою собственную проверку для целочисленных строк.Я знаю о is_numeric(), но этого недостаточно, поскольку он считает float числовым не только integers и is_int(), который не работает со строковыми числами.

Я сделал нечто подобное этому


$var1 = 'string';
$var2 = '123'; 

var_dump( (int)$var1 == $var1);// boolean true 
var_dump((int)$var2 == $var2);// boolean true

 var_dump((int)$var1);//int 0
 var_dump($var1);//string 'string' (length=6)

Как и ожидалось, второй дамп var выдает true, так как я ожидаю, что при произвольном сравнении php строки и целочисленные версии будут равны.

Однако с первой я не понимаю, почему это так.так.Я попытался привести к bool, и он все еще дает мне тот же результат.

Я попытался присвоить приведение var новой переменной и сравнить два, все тот же результат

Isэто что-то я делаю неправильно или это ошибка php?

*** Заметьте, я не сравниваю типы здесь.Я на самом деле пытаюсь воспользоваться тем, что int 0 не равно string 'string'.

Я написал свою целочисленную проверку по-другому, поэтому мне не нужны альтернативы для этого.

*** Edit Я провел дополнительную проверку, и оказалось, что 0 == 'string' также верно,Как это возможно?

*** Редактировать 2 Ниже приведено несколько правильных ответов на вопрос.Спасибо всем, кто ответил.

Ответы [ 7 ]

7 голосов
/ 13 июля 2011

Это не ошибка, это функция . Любая строка может быть приведена к целому числу, но приведение вернет 0, если строка не начинается с целочисленного значения. Кроме того, при сравнении целого числа и строки, строка приводится в целое число, а затем проверка производится по двум целым числам . Из-за этого правила любая произвольная строка «равна» нулю. (Чтобы обойти это поведение, вы должны использовать strcmp, поскольку он выполняет явное сравнение строк путем приведения всего, что передано к строке.)

Чтобы убедиться, что я имею дело с целым числом, я бы сначала использовал is_numeric, а затем преобразовал строку в int и проверил, соответствует ли stringified int входному значению.

if (is_numeric($value) && strcmp((int)$value, $value) == 0)
{
    // $value is an integer value represented as a string
}
2 голосов
/ 13 июля 2011

Вы допустили ошибку в своем сообщении, правильный вывод такой:

bool(true)
bool(true)
int(0)
string(6) "string"

Что происходит, это:

  1. Поскольку вы приводите переменную к целому числу и сравниваете ее с целым числом с произвольным сравнением ==, PHP сначала неявно приведёт строку к целому числу, более явная, но эквивалентная на 100% форма будет выглядеть так: if((int)$var1 == (int) $var1)
  2. см. 1), то же самое применимо и здесь
  3. Он печатает int(0), как и положено, поскольку он не может разобрать номер, вместо этого он возвращает 0.
  4. Отпечатки string(6) "string" - как и ожидалось
2 голосов
/ 13 июля 2011

Прежде всего в математиках '=' называется транзитивным b / c (A = B и B = C => A = C).

Это не относится к PHPs "=="!

(int)$var1 == $var1

В этом случае PHP преобразует 'строку' в 0 - это соглашение.

Тогда == - оператор неявно будет также приводить второй операнд 'строка'к целому числу -> а также 0.

Это приводит к истине.

2 голосов
/ 13 июля 2011

По данным php.net http://php.net/manual/en/language.operators.comparison.php:

var_dump(0 == "a"); // 0 == 0 -> true

Итак, я думаю, что это манипулирование типами и приведение обеих сторон к int. Затем сравнивается либо сумма значений ascii, либо значений ascii каждого соответствующего индекса в строке.

1 голос
/ 27 января 2017

Примечание: Этот ответ является ответом на связанный вопрос о шаблонизаторе Twig , который был помечен как дубликат и перенаправляет сюда.

Поскольку контекст отличается, этот ответ предоставляется тем членам сообщества SO, которые могут получить дополнительные сведения, относящиеся исключительно к .

TL; DR : см. Этот пост Чем отличаются операторы сравнения PHP (== double equals) и тождества (=== triple equals)?

Задача

Context

  • Шаблонный движок Twig (последняя версия с пт. 2017-01-27T05: 12: 25)

Сценарий

  • DeveloperYlohEnrohK использует оператор сравнения в выражении веточки
  • DeveloperYlohEnrohK замечает неожиданные результаты при использовании оператора сравнения равенства

Вопросы

  • Почему используется оператор сравнения равенства (==) производить неожиданнорезультаты в Twig?
  • Почему следующие результаты дают разные результаты?

    {{ dump(0 == 'somekey') }}          ==> true
    {{ dump(0|lower == 'somekey') }}    ==> false
    

Решение

Подводные камни

См. также

1 голос
/ 13 июля 2011

Если вы хотите сравнить типы переменных, вы должны использовать ===.

0 голосов
/ 30 ноября 2014

Вот функция, которая более тщательно проверяет целочисленную или целочисленную строку.

function isIntegerNumeric($val) {
  return (
    is_int($val)
      || (
        !is_float($val)
          && is_numeric($val)
          && strpos($val, ".") === false
      )
  );
}

Она относительно быстрая и не требует какой-либо проверки строки, если в этом нет необходимости.

...