☁ == ☀

Как знают программисты на ПХП, у этого языка есть одна неприятная особенность: при сравнении с приведением типов („==“) ПХП всё, что по его мнению похоже на число, преобразует в число:
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.
Причём, «похоже на число» — это не обязательно нечто десятичное:
var_dump("0x01" == "1"); // true
// но при этом
var_dump("0b01" == "1"); // false
var_dump("014" == "12") // false
Эта проблема косвенно проявляется при поиске в массиве. Казалось бы, строкового значения «1.5» в массиве нет:
var_dump(in_array("1.5", ["01.5000"])); // true
// правда есть специальный флаг для строгого стравнения, о котором почему-то мало кто знает:
var_dump(in_array("1.5", ["01.5000"], true)); // false
Но настоящая проблема вот в чём. ПХП, конечно, смотрит, похожа ли строка на то, что он считает числом, но никак не проверяет сможет ли он «съесть то, что укусил»:
var_dump("10000000000000000000000000000000" == "10000000000000000099999999999999"); // true
Сюрприз?

Почему так происходит. Всё очень просто. ПХП решает: внутри строки одни цифры, нужно преобразовать в число, в целый это не помещается, поэтому преобразую в число с плавающей точкой. Но число с плавающей точкой хранится с некой точностью, такова плата за его быструю обработку машиной.

В итоге при конвертации происходит потеря точности, левая и правая часть конвертируются в 1e31 (единица с с 31 нулём), которые равны между собой. Это может произойти, например, тогда, когда мы сравниваем «двумя равно» пару хешей, которые содержат только цифры.

Вывод: используете всегда только строгое равенство („===“) и вызовы функций сравнения с флагами, отключающими приведение типов, если только вы чётко не понимаете когда это правило можно нарушить. Но.

Есть конструкция, которой мы управлять не можем:
switch ("1.5") {
    case "0001.500": echo "пичалька"; // ещё какая!
}
Конструкция «switch» всегда использует нестрогое сравнение, об этом нужно помнить.
5 мая 2012 20:58

Segr (инкогнито)
6 мая 2012, 07:09

Превратим число в строку:
$a = "1.5";
switch ("`{$a}`") {
   case "`0001.500`": echo "кто здесь?";
}

Азат Разетдинов (razetdinov.ya.ru)
6 мая 2012, 07:42

Хорошо, что в яваскрипте этот тупняк на == и заканчивается. И switch, и indexOf используют ===.

bolk (bolknote.ru)
6 мая 2012, 07:55, ответ предназначен Азат Разетдинов (razetdinov.ya.ru):

В ПХП есть один тупняк есть (это как минимум): строка "0" считается false при всяких сравнениях:
var_dump(array_filter( [ 0, null, false, "0", "123", "000" ]));
array(2) {
[4]=>
string(3) "123"
[5]=>
string(3) "000"
}
или:
$a = "0"; $b = "000";
var_dump(empty($a), empty($b));
bool(true)
bool(false)

Ваше имя или адрес блога (можно OpenID):

Текст вашего комментария, не HTML:

Кому бы вы хотели ответить (или кликните на его аватару)