Комментарии 81
$x = true; или что-то новое?
+7
12 == "0xC"
В PHP7 ликвидировано такое поведение: 3v4l.org/nEgeH, wiki.php.net/rfc/remove_hex_support_in_numeric_strings
+4
«2.000000000000000123» == «2.000000000000000456»
Я этого не понял, должны ведь сравниваться как строки?
Я этого не понял, должны ведь сравниваться как строки?
+1
Всё, что похоже на число PHP преобразует тут в число. Довольно известное правило, где-то в документации есть.
0
ну да известно всем кроме интерпретатора:
var_dump(«2.000000000000000123» == «2.000000000000000456»); // false
var_dump(«2.000000000000000123» == «2.000000000000000456»); // false
0
Нулей просто мало. Вот:
php -r 'var_dump("2.00000000000000000123" == "2.00000000000000000456");'
bool(true)
0
да жесть, в принципе кроме этого всё объяснимо… но зачем так-то?!!!
+4
Потому что PHP традиционно мешает строки и числа в кучу, см., например, empty(«0»). Это из-за того, что снаружи ($_GET, $_POST и так далее) вообще всё приходит как строки, а создателям языка хотелось максимально упростить жизнь веб-мастеров в этом месте.
0
Ну и я бы не сказал, что «кроме этого всё объяснимо» :)) я таких примеров кучу знаю, например:
То есть уменьшение null даёт null, увеличение — единицу.
$ php -r '$a=null; var_dump(--$a); var_dump(++$a);'
NULL
int(1)
То есть уменьшение null даёт null, увеличение — единицу.
0
ну об этом в доке написано сразу: php.net/manual/en/language.operators.increment.php это можно объяснить, даже некую логику под это подвести (но я согласен, что это не ожидаемо)
но почему 2 строки сравниваются как числа нет
но почему 2 строки сравниваются как числа нет
0
Ну так и об операции сравнения написано в доке:
If you compare a number with a string or the comparison involves numerical strings, then each string is converted to a number and the comparison performed numerically.Более того!
These rules also apply to the switch statement.То есть:
$ php -r 'switch("0x000000") { case "0e0": var_dump("Duh!"); }'
string(4) "Duh!"
0
На самом деле в доке есть почти всё (за очень редким исключением), но очень уж забавны некоторые вещи. Например:
$ php -r 'var_dump([] < new stdclass); var_dump([] > INF);'
bool(true) // пустой массив меньше пустого класса
bool(true) // пустой массив больше бесконечности
0
"2.000000000000000123" == "2.000000000000000456"
у вас ошибка, это сравнение строк, а не float
+1
Это от разрядности зависит, нужно просто ноликов побольше.
var_dump("2.00000000000000000000000000000000123" == "2.00000000000000000000000000000000456"); // bool(true)
3v4l.org/pCMMn+3
"2.33a" == "2.33b" // false - сравниваем строки, все логично
"1e2" == "100" // true - зачем он их преобразовывает в числа? Для кого тут кавычки стоят?!
Хоть убейте, не понимаю, какого черты PHP при сравнении двух строк вообще пытается преобразовывать их в числа. Тип же совпадает.
+1
Тоже два float в строках:
«2.000000000000000123» == «2.000000000000000456»
false, сравниваются строки, приведение не выполняется
-1
Не поверил, решил проверить:
В итоге:
PHP 5.4.35, Win 7x86, OpenServer
<?php
$a1 = "1.000000000000000123";
$b1 = "1.000000000000000456";
$a2 = "2.000000000000000123";
$b2 = "2.000000000000000456";
if($a1 == $b1) echo $a1.' == '.$b1;
else echo $a1.' != '.$b1;
echo '<br>';
if($a2 == $b2) echo $a2.' == '.$b2;
else echo $a2.' != '.$b2;
В итоге:
1.000000000000000123 != 1.000000000000000456
2.000000000000000123 != 2.000000000000000456
PHP 5.4.35, Win 7x86, OpenServer
+3
Паскаль нас учил писать =
Си учил на писать ==
Пхп нас учит писать ===
Си учил на писать ==
Пхп нас учит писать ===
+13
12 == «0xC»
Конечно, true.
Спасибо. Хорошая шпаргалка.
Конечно, true.
Спасибо. Хорошая шпаргалка.
0
Почитал, поужасался. К концу остался вопрос: а что, вот так действительно кто-то пишет?
Я к тому, что если идёт более-менее осмысленное написание кода то вот такого понаписать сложно (чтобы (string) «false» сравнивать с (boolean) true, 12 == «0xC» и тому подобное).
Вот честное слово, с подобными проблемами сравнения последний раз сталкивался может быть лет пять назад.
Явное приведение типов, фильтрация входящих данных и принцип «никогда не доверяй тому, что пришло от пользователя» — избавляют от подобных проблем. Разве нет?
Я к тому, что если идёт более-менее осмысленное написание кода то вот такого понаписать сложно (чтобы (string) «false» сравнивать с (boolean) true, 12 == «0xC» и тому подобное).
Вот честное слово, с подобными проблемами сравнения последний раз сталкивался может быть лет пять назад.
Явное приведение типов, фильтрация входящих данных и принцип «никогда не доверяй тому, что пришло от пользователя» — избавляют от подобных проблем. Разве нет?
+3
Ну вот сравнение «100» == «1e2» может в какой-то задаче попасться. Скажем, 2 пользователя с такими никами — и вроде все нормально, правильные данные от пользователя, сравниваем строки со строками… А нет, PHP за нас что-то додумывает!
+3
Бывают не очевидные случаи. Приходит вам с клиента $POST, а там строки, а вы вполне можете думать, что там целые числа и сравниваете эти строки с числами через ==. Как вариант.
0
Нормальные люди конечно так никогда не пишут. Это статья больше для развлечения, чем для использования всего этого на практике. Маленькие перлы языка =)
+1
Мое любимое:
setlocale('LC_ALL', 'ru_RU.UTF-8');
$f = 0.9;
$s = (string)$f;
$f2 = (float)$s;
var_dump($f, $s, $f2);
setlocale('LC_ALL', 'ru_RU.UTF-8');
$f = 0.9;
$s = (string)$f;
$f2 = (float)$s;
var_dump($f, $s, $f2);
+2
double(0.9)
string(3) «0.9»
double(0.9)
А что должно было быть?
+1
Похоже, вы пренебрегли первой командой
-1
Да нет, скопировал целиком, правда если включить e_depricated, то можно увидеть:
Замена 'LC_ALL' на LC_ALL убирает предупреждение, вывод не меняется. php 5.4.12, если это важно.
Deprecated: setlocale(): Passing locale category name as string is deprecated. Use the LC_* -constants instead in test.php on line 2
Замена 'LC_ALL' на LC_ALL убирает предупреждение, вывод не меняется. php 5.4.12, если это важно.
0
Локаль «ru_RU.UTF-8», видимо, в системе отсутствует. Смысл в том, чтобы установить такую локаль, где десятичный разделитель — запятая.
Если у вас unix-система, посмотрите список локалей с помощью команды locale -a. Если Windows — не знаю :-)
Если у вас unix-система, посмотрите список локалей с помощью команды locale -a. Если Windows — не знаю :-)
+1
> А что должно было быть?
double(0.9)
string(3) «0,9»
double(0)
double(0.9)
string(3) «0,9»
double(0)
0
Мне вот не понятно, как после такого люди добровольно выбирают похапе в проекты?
-3
Это же пограничные случаи, а не правило, при этом никто ж не запрещает использовать ===
Думаю пасхалки есть в любом языке, просто в PHP их немного больше :)
Думаю пасхалки есть в любом языке, просто в PHP их немного больше :)
+6
s/немного/намного/
fixed ;)
fixed ;)
+1
Ну так каждая пасхалочка у тебя отнимает (условно) час времени. Поэтому и не ясно, зачем брать инструмент с пасхалками, когда есть такой же без. А час времени лучше потратить на себя/жену/детей.
-3
Половина кода из статьи будет работать в JS. как? как люди выпирают писать на js?
+4
Можно подумать есть выбор.
+4
У js альтернативы как таковой нет. У похапе же навалом. Да и уровень идиотии у js не такой зашкаливающий.
-3
Да и уровень идиотии у js не такой зашкаливающий.
Если и не такой зашкаливающий, то только потому, что в PHP встроенного функционала на два порядка больше, там было место, где развернуться. В процентном соотношении они идут плечо к плечу.
+6
www.wtfjs.com
+2
У js альтернативы как таковой нет.
TypeScript ;-)
0
Напомнило :)
![](https://habrastorage.org/r/w780q1/getpro/habr/comment_images/cc6/041/94a/cc604194af3224f0a1a985cbc707bb5a.jpg)
(Только это JavaScript)
![](https://habrastorage.org/getpro/habr/comment_images/cc6/041/94a/cc604194af3224f0a1a985cbc707bb5a.jpg)
(Только это JavaScript)
+9
Прочитал заголовок как «PHP — баллада о двух стульях» (ну вы поняли). Закрыл вкладку, т.к. всё уже было сказано несколько лет назад: habrahabr.ru/post/142140
-3
Сравнивать float'ы нужно всегда с учетом погрешности в любом языке, а не только в PHP.
+5
Решение задачки: $x == 1 && $x == 2
x=...
при $x = true;
+1
ИМХО, резюме должно быть такое: юзайте ===
0
Кому нужна транзитивность в PHP, те используют === тождественное сравнение активных типов (без преобразований). Но статья классная, хороший справочник)
+2
В большинстве случаев большинство, к счастью, эти примеры так и остаются просто любопытными случаями, но есть то на чем наверное рано или поздно спотыкается любой пхпшник, при том иногда довольно больно спотыкается — это empty('0')==true, возможно стоило упомянуть в статье и об этом, оно в принципе о том же.
0
На работе php-шники делают нам REST-API. Когда десериализуем Json происходит сущий ад. Числа в одном и том же запросе то в string, то во float, а если число 1, то приходит int. Писали, ругались. Проблемы они не видят, видимо слово «типы» им вообще не знакомо. Не хочу обижать всех, кто пишет на php, но сам язык предрасположен к написанию говнокода. В новых версиях намечается прогресс, хоть это радует.
0
На работе сишники присылают нам в php xml, валидацию не проходит, даже кавычки расставлены неверно. Не хочу обижать никого, но c++ предрасположен к генерации невалидного xml. Проблемы они не видят, их собственноручная библиотека проходит все тесты. Надеюсь в версии c++ 15 эту проблему решат, а пока хотим перейти на nodejs.
+1
Если в c++ вы указали тип поля int, то string вы туда никак не засунете. Чего не скажешь о php. Я вам реальный случай из жизни привожу, а вы передёргиваете.
0
Вы рассказали реальный случай из жизни неквалифицированных работников (и видимо такого же отдела кадров и руководителя тех. отдела). Не понятно, причем тут PHP абсолютно, именно поэтому я привела пример с кавычками, а не типами.
И если вы не можете выставить элементарные требования к формату, то хоть кто вам будет слать JSON, и хоть с какими типами. А если формат есть, а работа выполняется некачественно, то можно обвинять язык, ОС, железо, ну вы поняли.
И если вы не можете выставить элементарные требования к формату, то хоть кто вам будет слать JSON, и хоть с какими типами. А если формат есть, а работа выполняется некачественно, то можно обвинять язык, ОС, железо, ну вы поняли.
0
А зачем ругаться? Есть такая штука json-schema. И тут как бы одно из двух либо результат ей соответсвует и тогда никаких претензий друг к другу. Либо нет, тогда значит апи не соответствует спеке.
0
Всё это говорит о том, что программисту надо воздерживаться от неоднозначностей, предпочитать ===, а не ==, и вообще, писать ясный и читаемый код. При желании в любом языке можно найти разные «пасхалки», глюки и неоднозначности, — только зачем их все пихать в код? Опять же, юнит-тесты на что?
+1
Зарегистрируйтесь на Хабре, чтобы оставить комментарий
Приведение типов в PHP == табурет о двух ножках?