Website development
PHP
Programming
June 2015 5

Приведение типов в PHP == табурет о двух ножках?

image

— В PHP приведение типов работает нормально, надо только включать здравый смысл.
— А чего там, просто сравниваешь и все…
— Ого, глюк какой-то в PHP, смотри, сравниваю два флоата, они должны быть одинаковые, а он мне говорит, что они не равны.
— А, ну когда число со строкой сравниваешь, перебирать надо, что сработает.

Слышали что-то подобное от коллег или может быть у самих возникали подобные ситуации? Тогда вот вам пятничный пост с примерами про приведение типов, как это работает с оператором ==.

Буду краток, дальше будут только примерчики. А к тебе, дорогой читатель, просьба. Некоторые ответы спрятаны под спойлер. Перед тем, как заглянуть в ответ под спойлером, попробуй ответить сам. За каждый правильный ответ заслуженно прибавляй себе по баллу. В конце поста в опросе не забудь проставить свой результат. Договорились?
Тогда поехали.
Начнем с чисел

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

Для порядка проверяем очевидное:

11 == 11 // true, воистину
12 == 11 // false, само собой
12 == 0xC // true, сравниваем с 16-ричным

Как насчет такого сравнения?

12 == "0xC"

Попробуйте ответить
true. Да, тут значение в строке преобразовалось в целое с учетом системы счисления, здорово, правда?

А если так попробуем?

12 == 014

Чур не подглядываем, помните?
true. А как иначе? 014 — это же 12 в 8-ричной системе счисления.

Теперь так:

12 == "014"

Результат...
false. Те, кто хотел и тут true, умерьте свои требования, «0xC» преобразовалось в 12 и хватит.

И еще так:

14 == "014"

Равно...
true, вполне ожидаемо с учетом предыдущего примера.

Тут вроде все наглядно:

014 == "014"

Правильный ответ...
false, хотя чисто визуально это трудно заметить сходу, особенно, если читаешь чужой код.

Внимание:

0 == "0,9"

Ответ...
true, чего? А, ну да, так false: 0 == «0.9». Запятая посчиталась строковым символом и она и все после нее отбросилось.

Сравним такие значения:

"1e2" == "100"

Получим...
true, так как 1 умножить на 10 в квадрате равно 100.

0b11 == 3 // true, 0b - это относится к двоичной системе

А если 0b11 в строке?

"0b11" == 3

Сравниваем...
false, для 16-ричной системы это работает, а для двоичной — извините.

Теперь попробуем так:

2.333 == "2.333petrovich" // true, тут Петрович в конце строки и поэтому исключается из сравнения.
2.333 == "ivanovich2.333" // false, а тут Иванович вначале, поэтому сравнение идет со строкой.
0 == "ivanovich2.333" // true, строка равна нулю.


А тут попробуйте сами:
"2.33a" == "2.33b"

И получаем...
false, тут никакого преобразования нет, сравниваются строки.

233 == "233w1" // true, по аналогии с Петровичем

Почти тоже самое:

233 == "233e1"

Ответ...
false, да, кто заметил, тут 233 * 10.

"233" == "233w1" // false
233 == "233*1" // true

А если так скалькулировать?

233 == "233*2"

Вот...
Правильно, снова true, по аналогии с Петровичем.

0 == "" // true

Не подглядывайте, сперва сами:

"0" == ""

Пытаемся включить здравый смысл...
false, смиритесь.

"1.000000000000000123" == "1.000000000000000456" // false, логично, разные ж числа.

Тоже два float в строках:

"2.000000000000000123" == "2.000000000000000456"

Догадались?
true, не удивляйтесь, с виду числа хоть и разные, но 2 == 2, тут все до 2 округлилось.

Булевы сравнения

Раз с числами все проще простого и все ответили правильно, то вот еще простые примерчики.

Сперва такой каламбур… вспомнился анекдот про Поручика, но пожалуй воздержусь.

"true" == true // true
"false" == true // true, строка равна true
"false" == false // false, строка равна true
"true" == false // false, строка равна true

Тут все просто и понятно.

true == "0" // false, тут уже идет сравнение не со строкой, а с нулем
true == "00" // true, а тут со строкой...
true == 00 // false
true == "00" + 0 // false, тут к строке с нулем 0 прибавили

А если так прибавить:

true == "01" + 0

То получим...
true, а тут уже к 1 прибавление.

true == "0x" + 0 // false

Пробел пред нулем:

true == " 0"

Сверяемся...
true, хотя кто-то мог ожидать, что пробел отбросится и будет сравнение с нулем.

true == 0x0 // false
true == "0x0" // true, так-то, тут уже не 0, а строка
true == "0.0" // true, и тут строка


true == " " // true
true == [] // false, пустой массив - это false
true == [0] // а массив с нулем - true

А если так?

true == [[]]

Проверяем...
true, тут массив что-то себе содержит, пустой массив.

NULL

Позвольте еще несколько сравнений, теперь с null.

null == false // true,
null == 0 // true,
false == "0" // true,

Попробуйте догадаться по аналогии:

null == "0"

Получаем...
false, видимо, надо просто запомнить.

null == [] // true, так как массив пустой
null == [0] // false, не пустой массив все-таки


Массивы

Ну и для особо любознательных — сравнения массивов.

Тут надеюсь, сами догадаетесь, только не подглядывайте:

[] == 0

Сверяем...
Точно, false, хотя null == 0 и [] == null.

[0] == 0 // false,

В документации сказано, что "$a == $b — TRUE в случае, если $a и $b содержат одни и те же пары ключ/значение".
Проверим, как именно работает это утверждение. тем более, что в доке ничего ни сказано про то, как сравниваются ключи.

[1 => 1] == [1 => 1] // true
[1 => 1] == ["1" => 1] // true, при этом:
[1 => 1] == ["0x1" => 1] // false, при том, что если отдельно сравнить ключи таким образом:
array_keys([1 => 1]) == array_keys(["0x1" => 1]) // true
Зато:
[1 => 1] == [1 => "0x1"] // true

Загадочка

И на десерт загадочка (загадка не от меня, коллега однажды ее мне дал).
Может ли когда-либо выполниться условие $x == 1 && $x == 2, если может, то когда, если нет, то почему?

А как-же резюме?

А какое тут резюме, табурет с двумя ножками вполне может быть использован по назначению. Более того, он имеет свои положительные стороны, например, помогает держать в тонусе вестибулярный аппарат и ягодицы. Так что читаем доки, набиваем шишки и все будет хорошо.
Сколько баллов получилось?
2.6% 18 15
1.2% 17 7
3% 16 17
2.4% 15 14
3% 14 17
3.7% 13 21
6% 12 34
3.2% 11 18
7.1% 10 40
2.4% 9 14
3% 8 17
1.4% 7 8
1.2% 6 7
0.8% 5 5
0.5% 4 3
0.7% 3 4
0.1% 2 1
0.7% 1 4
56.1% 146 == true 315
Voted 561 user. Passed 421 user.
+29
47.6k 224
Support the author
Comments 81
Top of the day