Понимание PHP & (амперсанд, битовый и) оператор - PullRequest
56 голосов
/ 01 марта 2009

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

Но что на самом деле означает "&"?

Ответы [ 5 ]

59 голосов
/ 01 марта 2009

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

  01101010
& 01011001
= 01001000

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

25 голосов
/ 02 марта 2009

Двумя операциями, которые являются фундаментальными для двоичных систем, являются ИЛИ и И.

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

И означает «если включены и А, и В». Пример реального мира - два переключателя в серии. Ток будет проходить, только если оба позволяют току.

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

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

Вот почему:

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

Принимая во внимание

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

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

Другие фундаментальные операции с двоичными системами включают NOT и XOR. NOT означает «если 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, ваши целые числа будут иметь большую точность, чем числа с плавающей запятой.

18 голосов
/ 01 марта 2009

Также интересно узнать о побитовом и 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
13 голосов
/ 31 января 2010

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

if(func1() && func2())

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

if(func1() & func2())

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


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

12 голосов
/ 17 марта 2009

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

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

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

...