У меня есть проблема, которая сбивает меня с толку. Я заметил это раньше, но до сих пор не обращал на это внимания. Я пытался написать собственный чек для целых строк. Я знаю 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
и это все равно дает мне тот же результат.
Я попытался присвоить cast var новому переменному и сравнить два, все тот же результат
Это что-то я делаю неправильно или это ошибка php?
*** Примечание. Я не сравниваю типы здесь. Я на самом деле пытаюсь воспользоваться тем фактом, что int 0
не равно string 'string'
.
Я написал свою целую проверку по-другому, поэтому мне не нужны альтернативы для этого.
*** Edit. Я сделал некоторую дополнительную проверку, и получается, что 0 == 'string'
истинно. Как это возможно?
*** Изменить 2 На вопрос несколько правильных ответов. Спасибо всем, кто ответил.
Это не ошибка, это особенность . Любая строка может быть записана в целое число, но приведение будет возвращать 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 }
Согласно php.net http://php.net/manual/en/language.operators.comparison.php :
var_dump(0 == "a"); // 0 == 0 -> true
Итак, я думаю, что это жонглирование типами, и фактически литье обеих сторон в int. Затем сравните либо сумму значений ascii, либо значений ascii каждого соответствующего индекса в строке.
Прежде всего в математиках '=' называется транзитивным b / c (A = B и B = C => A = C).
Это не относится к PHP «==»!
(int)$var1 == $var1
В этом случае PHP будет отличать 'string' до 0 – это соглашение.
Тогда == – оператор будет неявно иметь вторую операнду 'string', также быть отлитой в integer ->, а также 0.
Это приводит к истине.
Вы сделали ошибку со своим сообщением, правильный результат:
bool(true) bool(true) int(0) string(6) "string"
Что происходит, так это:
==
, PHP сначала будет вводить строку в целочисленное целое, а более явную, но 100% эквивалентную форму: if((int)$var1 == (int) $var1)
int(0)
, как и следовало ожидать, потому что он не может проанализировать число, оно вместо этого вернет 0
. string(6) "string"
– как и ожидалось Если вы хотите также сравнить типы переменных, вы должны использовать ===
.
Примечание. Этот ответ отвечает на соответствующий вопрос о движке шаблонов Twig , который был помечен как дубликат, и перенаправляет сюда.
Поскольку контекст отличается, этот ответ предоставляется тем членам сообщества SO, которые могут извлечь выгоду из дополнительных сведений, специально связанных с веточкой исключительно.
TL; DR : см. Этот пост. Чем отличаются отношения равенства PHP (== double equals) и идентичности (=== triple equals)?
==
) дает неожиданные результаты в Twig? Почему следующие результаты дают разные результаты?
{{dump (0 == 'somekey')}} ==> true {{dump (0 | lower == 'somekey')}} ==> false
===
в Twig гораздо реже приводит к неожиданным результатам. ===
же, как стандартный PHP ===
используя то same as
Вот функция, которая более строго проверяет либо строку int, либо целочисленную строку.
function isIntegerNumeric($val) { return ( is_int($val) || ( !is_float($val) && is_numeric($val) && strpos($val, ".") === false ) ); }
Это относительно быстро и позволяет избежать проверки строки, если это не так.