Я часто использую ($var & 1)
в своем коде, который возвращает true, если $var
является нечетным числом, и false, если это четное число.
Но что на самом деле делает «&»?
Я часто использую ($var & 1)
в своем коде, который возвращает true, если $var
является нечетным числом, и false, если это четное число.
Но что на самом деле делает «&»?
& является двоичным and
. Если у вас есть двоичное значение, и вы and
используете другое двоичное значение, то результатом будет побитовое and
из двух. Пример:
01101010
& 01011001
= 01001000
Крайний правый бит равен либо 1 (и в этом случае число нечетное), либо 0, и в этом случае число четное. Если вы &
число с 1, вы смотрите только на младший значащий бит, а if проверяет, является ли число 1 или 0. Как уже упоминалось, посмотрите на побитовые операторы для получения информации о том, как они работают.
$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, ваши целые числа в любом случае будут иметь большую точность, чем числа с плавающей запятой.
Это также интересно знать о побитовом и 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
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.
В дополнение к другим ответам, стоит отметить, что
if(func1() && func2())
Будет вызывать func2()
только в том случае, если func1()
возвращает true ("ленивая оценка"), тогда как
if(func1() & func2())
Будет вызывать обе функции независимо, но таблицы истинности для обеих будут одинаковыми (при условии, что они возвращают логические значения).
thomasrutter указывает (в комментариях ниже), что вы, вероятно, не должны делать последнее на практике. (A & B)
не обязательно будет иметь ту же правдивость, что и (A && B)
, особенно когда A
и B
являются целыми числами. например, если A=1 и B=2 (оба верны), A и B будут ложными, тогда как A && B верны. Кроме того, другой разработчик может подумать, что это опечатка, и «исправить» ее до двух амперсандов.
func1() && func2()
оценивается как true
, а func1() & func2()
оценивается как 0
. Даже в тех случаях, когда это работает, я бы не назвал это хорошей практикой кодирования, поскольку она основана на побочных эффектах порядка вычисления и преобразования типов, что затрудняет чтение и понимание цели кода. Любой человек, просматривающий код, может предположить, что это опечатка.
- person thomasrutter; 28.01.2014
$var%2==1
, но это, вероятно, более эффективно. Спасибо. +1 - person mpen   schedule 31.01.2010