Понимание PHP & (амперсанд, побитовое и) оператор

Я часто использую ($var & 1) в своем коде, который возвращает true, если $var является нечетным числом, и false, если это четное число.

Но что на самом деле делает «&»?


person ryonlife    schedule 01.03.2009    source источник
comment
Для кого-то вопрос не простой, и он просит подробного объяснения об операторе, как видно по ответу, который он принял.   -  person Ólafur Waage    schedule 01.03.2009
comment
@Olafur - оператор & довольно прост. Ему не нужно подробное объяснение, ему нужно объяснение AN, потому что он использовал его, не зная, что именно он делает. Хотя я восхищаюсь его готовностью признать, что он этого не знает, и желанием научиться этому, это все же больше вопрос Google.   -  person Chris Lutz    schedule 01.03.2009
comment
Дело не в том, прост ли ответ, а в том, что его размещение здесь означает просто копирование его откуда-то еще. Это избыточно. Мне кажется, что некоторые люди действительно используют SO, чтобы убить свободное время. Может быть, я немного предвзят, но мне нравится SO для головоломок, а не для вопросов в чате.   -  person Arne    schedule 01.03.2009
comment
Разве не было бы хорошо, если бы вы могли найти ответ на любой вопрос по программированию на SO? Это могло бы произойти только в том случае, если бы задавались как простые вопросы, так и головоломные. Исходя из этого, мне кажется, это правильный вопрос.   -  person da5id    schedule 02.03.2009
comment
Не стоит недооценивать количество людей, которые являются успешными программистами, но не знают, что делает побитовая операция. Это правильный вопрос, и полное понимание помогает объяснить низкоуровневую работу электрических цепей, шифрование и хеширование и т. д.   -  person thomasrutter    schedule 02.03.2009
comment
Нельзя программировать php, не зная, где находятся онлайн-руководства. И есть очевидный раздел для операторов.   -  person dkretz    schedule 04.03.2009
comment
Я должен добавить, что в дополнение к поиску в Google, прежде чем я задал вопрос, я, конечно, также посетил документы PHP. Существует оглавление, посвященное операторам, со ссылками на 12 подробных страниц. Мне не удалось получить объяснение, и страница Bitwise не объясняет &...   -  person ryonlife    schedule 04.03.2009
comment
... Не говоря о том, что нет в руководстве, но я не мог найти его тогда и не могу найти до сих пор. Я стараюсь проявить некоторую степень должной осмотрительности, прежде чем задавать вопросы о SO. Если вы считаете, что вопрос излишен, зачем мучиться? Ответь, проголосуй против или иди дальше.   -  person ryonlife    schedule 04.03.2009
comment
Качество ответов, которые я получил здесь (включая подробные объяснения двоичного кода), намного лучше, чем мне удалось найти за 15 минут моих собственных исследований в Google, документах PHP и SO. Вот что делает это сообщество таким ценным ресурсом.   -  person ryonlife    schedule 04.03.2009
comment
Хе. Для меня очевидно, что делает этот код, но я никогда не думал использовать его таким образом. Я бы сделал $var%2==1, но это, вероятно, более эффективно. Спасибо. +1   -  person mpen    schedule 31.01.2010


Ответы (5)


& является двоичным and. Если у вас есть двоичное значение, и вы and используете другое двоичное значение, то результатом будет побитовое and из двух. Пример:

  01101010
& 01011001
= 01001000

Крайний правый бит равен либо 1 (и в этом случае число нечетное), либо 0, и в этом случае число четное. Если вы & число с 1, вы смотрите только на младший значащий бит, а if проверяет, является ли число 1 или 0. Как уже упоминалось, посмотрите на побитовые операторы для получения информации о том, как они работают.

person Marius    schedule 01.03.2009
comment
Можете ли вы привести несколько полезных примеров, для чего это действительно можно использовать? потому что нечетное или четное вы можете сделать и по модулю, верно. Что гораздо проще понять и читабельнее, скажем $is_even = $x % 2 === 0; $is_odd = !$is_even; - person Toskan; 14.02.2020

Две операции, лежащие в основе двоичных систем, — это ИЛИ и И.

ИЛИ означает «если либо A включен, либо B включен». Примером из реальной жизни могут быть два переключателя, включенных параллельно. Если любой пропускает ток, то ток проходит.

И означает «если оба A и B включены». Реальный пример — два последовательно соединенных переключателя. Ток будет проходить только в том случае, если оба пропускают ток.

В компьютере это не физические переключатели, а полупроводники, и их функции называются логическими вентилями. Они делают то же самое, что и переключатели — реагируют на ток или его отсутствие.

Применительно к целым числам каждый бит одного числа объединяется с каждым битом другого числа. Итак, чтобы понять побитовые операторы ИЛИ и И, вам нужно преобразовать числа в двоичные числа, а затем выполнить операцию ИЛИ или И для каждой пары совпадающих битов.

Поэтому:

00011011 (odd number)
AND
00000001 (& 1)
== 
00000001 (results in 1)

В то время как

00011010 (even number)
AND
00000001 (& 1)
==
00000000 (results in 0)

Таким образом, операция (& 1) сравнивает самый правый бит с 1, используя логику И. Все остальные биты фактически игнорируются, потому что что угодно И ничего не является ничем. Четное число в двоичном формате также является четным числом в десятичной системе счисления (10 кратно 2).

Другие основные операции с двоичными системами включают NOT и XOR. НЕ означает «если A выключен» и является единственной формой логического элемента, который принимает только один сигнал или «параметр» вместо двух. XOR означает «если включен либо A, либо B, но не оба». А еще есть NAND, NOR и NXOR, которые просто НЕ сочетаются с AND, OR и XOR, т.е. NAND означает «если A и B не оба включены».

В программировании оператор

& means AND,
| means OR, 
~ means NOT, and
^ means XOR.

Остальные можно составить, комбинируя их, например:

~ (a & b) is equivalent to a NAND operation

Примечание для PHP

Побитовые операторы не работают со значениями с плавающей запятой, а в PHP значения с плавающей запятой будут сначала неявно преобразованы в целые числа. Числа вне диапазона, которые могут быть выражены как целые числа, будут усечены до нуля, то есть все числа выше PHP_INT_MAX будут выглядеть «четными» в выражении ($num & 1)). Если вы хотите поддерживать числа за пределами PHP_INT_MIN/PHP_INT_MAX, вам понадобится fmod($num, 2). Однако если вы используете 64-разрядный PHP, ваши целые числа в любом случае будут иметь большую точность, чем числа с плавающей запятой.

person thomasrutter    schedule 02.03.2009
comment
Лично я думаю, что это объясняет проблему лучше, чем принятый ответ, поскольку на самом деле объясняет, что за кулисами делают побитовые операции, что крайне важно для их понимания и использования. - person Byson; 08.09.2014

Это также интересно знать о побитовом и PHP:

/**
 * Regular
 */
echo (true && true); // 1
echo (true && false); // nothing

echo (true || false); // 1
echo (false || false); // nothing

echo (true xor false); // 1
echo (false xor false); // nothing

/**
 * Bitwise
 */
echo (true & true); // 1
echo (true & false); // 0

echo (true | false); // 1
echo (false | false); // 0

echo (true ^ false); // 1
echo (false ^ false); // 0
person Ólafur Waage    schedule 01.03.2009
comment
Этот ответ на самом деле не объясняет, чем && отличается от &, на мой взгляд, очень хорошо. && приводит оба параметра к логическим значениям и сравнивает один бит. & сравнивается побитовым способом: каждый бит одного параметра сравнивается с каждым битом другого. - person thomasrutter; 02.03.2009
comment
регулярный известен как логический и / или - person Ryan Kearney; 15.09.2009
comment
Также важно знать, что побитовые операторы, такие как & и | оперировать целыми числами. Примеры в этом ответе работают только потому, что true преобразуется в 1, а false преобразуется в 0. Если бы у вас было echo ("cheese" & 4), он вывел бы ноль, а echo ("cheese" && 4) вывел бы true. - person thomasrutter; 28.01.2014

Я знаю, что ваш вопрос касается понимания побитового оператора, и принятый ответ хорошо объясняет это. Но для приведенного вами примера я не могу не порекомендовать вам вместо этого использовать оператор по модулю:

($var % 2) /* instead of */ ($var & 1)

Потому что это ясно дает понять, что вы проверяете, является ли число нечетным (не делится на два), и оно является более общим, поэтому вы можете использовать ($var % 3) таким же образом и сделать вывод, как это работает для любого N.

person Pat    schedule 16.03.2009

В дополнение к другим ответам, стоит отметить, что

if(func1() && func2())

Будет вызывать func2() только в том случае, если func1() возвращает true ("ленивая оценка"), тогда как

if(func1() & func2())

Будет вызывать обе функции независимо, но таблицы истинности для обеих будут одинаковыми (при условии, что они возвращают логические значения).


thomasrutter указывает (в комментариях ниже), что вы, вероятно, не должны делать последнее на практике. (A & B) не обязательно будет иметь ту же правдивость, что и (A && B), особенно когда A и B являются целыми числами. например, если A=1 и B=2 (оба верны), A и B будут ложными, тогда как A && B верны. Кроме того, другой разработчик может подумать, что это опечатка, и «исправить» ее до двух амперсандов.

person mpen    schedule 31.01.2010
comment
Хотя это работает большую часть времени, это не всегда работает, например, когда функции возвращают числа. Допустим, func1() возвращает 1, а func2() возвращает 4. func1() && func2() оценивается как true, а func1() & func2() оценивается как 0. Даже в тех случаях, когда это работает, я бы не назвал это хорошей практикой кодирования, поскольку она основана на побочных эффектах порядка вычисления и преобразования типов, что затрудняет чтение и понимание цели кода. Любой человек, просматривающий код, может предположить, что это опечатка. - person thomasrutter; 28.01.2014