68

I often use ($var & 1) in my code, which returns true if $var is an odd number and false if it's an even number.

But what does "&" actually do?

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
ryonlife
  • 6,563
  • 14
  • 51
  • 64
  • For some the question is not simple, and he is asking for a detailed explanation about the operator, as you can see by the answer he accepted. – Ólafur Waage Mar 01 '09 at 18:19
  • @Olafur - the & operator is fairly simple. He doesn't want a detailed explanation, he wants AN explanation, because he's been using it without knowing what exactly it does. While I admire his willingness to admit that he doesn't know it and desire to learn it, it's still more of a Google question. – Chris Lutz Mar 01 '09 at 18:39
  • It's not about wether the answer is simple, but if posting it here means simply copying it from somewhere else. This is redundant. It feels to me, that some people are really using SO to kill spare time. Maybe I'm a bit biased, but I like SO for puzzles and not for chat-like questions. – Arne Mar 01 '09 at 18:41
  • 6
    Wouldn't it be good if you could find an answer for *any* programming question on SO? The only way this would ever happen is if "simple" questions get asked as well as "puzzle" ones. On that basis, methinks this a valid question. – da5id Mar 01 '09 at 22:41
  • 10
    Don't underestimate the number of people who are successful programmers but don't know what a bitwise operation does. It's a valid question and a thorough understanding helps explain low level workings of electric circuits, encryption and hashing, etc. – thomasrutter Mar 02 '09 at 05:41
  • 1
    One can't program php without knowing where the online manuals are. And there's an obvious section for "Operators". – dkretz Mar 04 '09 at 04:19
  • I should add, in addition to Googling before I asked the question, of course I also visited the PHP docs. There's a TOC dedicated to operators with links to 12 detailed pages. I was unable to get an explanation, and event the Bitwise page does not explain "&"... – ryonlife Mar 04 '09 at 06:11
  • 16
    ... Not saying isn't not in the manual, but I couldn't find it then and can't find it even now. I try to exercise some degree of due diligence before asking questions on SO. If you think a question is unnecessary, why give a hard time? Answer, vote it down or move on. – ryonlife Mar 04 '09 at 06:15
  • 11
    The quality of answers I received here (which included detailed explanations on binary) are far better than I was able to find in my own 15 minutes of research on Google, PHP docs and SO. That's what makes this community such a valuable resource. – ryonlife Mar 04 '09 at 06:18
  • Heh. It's obvious to me what that code does, but I never thought of using it like that. I would have done `$var%2==1`, but this is probably more efficient. Thanks. +1 – mpen Jan 31 '10 at 19:21

5 Answers5

64

& is binary and. If you have a binary value, and you and with another binary value, then the result will be the bitwise and of the two. An example:

  01101010
& 01011001
= 01001000

The rightmost bit is either a 1 (and in that case the number is an odd number) or it is a 0, in which case the number is even. If you & a number with 1, you only look at the least significant bit, and the if checks if the number is a 1 or a 0. As others have mentioned, look at the bitwise operators for info on how they work.

Marius
  • 57,995
  • 32
  • 132
  • 151
  • can you give a bunch of useful examples what one can actually use it for? because odd or even you can do as well with modulo, right. Which is far easier to understand and more readable say `$is_even = $x % 2 === 0; $is_odd = !$is_even;` – Toskan Feb 13 '20 at 22:18
30

Two operations which are fundamental to binary systems are OR and AND.

OR means 'if either A is on or B is on'. A real world example would be two switches in parallel. If either is allowing current through, then current passes through.

AND means 'if both A and B is on'. The real world example is two switches in series. Current will only pass through if both are allowing current through.

In a computer, these aren't physical switches but semiconductors, and their functionality are called logic gates. They do the same sorts of things as the switches - react to current or no current.

When applied to integers, every bit in one number is combined with every bit in the other number. So to understand the bitwise operators OR and AND, you need to convert the numbers to binary, then do the OR or AND operation on every pair of matching bits.

That is why:

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

Whereas

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

The (& 1) operation therefore compares the right-most bit to 1 using AND logic. All the other bits are effectively ignored because anything AND nothing is nothing. An even number in binary is also an even number in decimal notation (10 is a multiple of 2).

Other fundamental operations to binary systems include NOT and XOR. NOT means 'if A is off' and is the only form of logic gate that takes only one signal or 'parameter' instead of two. XOR means 'if either A or B is on, but not both'. And then there are NAND, NOR, and NXOR, which are basically just NOT combined with AND, OR, and XOR, ie NAND means 'if A and B are not both on'.

In programming, the operator

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

The others can be made up by combining these, for example:

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

PHP specific note

Bitwise operators do not work on floating-point values, and in PHP float values will be implicitly converted to integers first. Numbers outside the range that can be expressed as integers will be truncated to zero - that is, all numbers over PHP_INT_MAX will look "even" in the expression ($num & 1)). If you want to support numbers outside of PHP_INT_MIN/PHP_INT_MAX, you'll need fmod($num, 2). If, however, you're on 64-bit PHP your integers will have greater precision than floats anyway.

thomasrutter
  • 114,488
  • 30
  • 148
  • 167
  • 4
    Personally I think this explains the issue better than the accepted answer, as it actually explains what bitwise operations do behind the scenes, which is **crucial** for understanding and using them. – Byson Sep 08 '14 at 07:16
19

This is also interesting to know about bitwise and 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
Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Ólafur Waage
  • 68,817
  • 22
  • 142
  • 198
  • 1
    This answer doesn't really explain how && is different to & very well in my opinion. && casts both parameters to boolean, and is like comparing a single bit. & compares in a bitwise fashion: each bit in one parameter is compared with each bit in the other. – thomasrutter Mar 02 '09 at 05:37
  • 3
    "regular" is known as the logical and/or – Ryan Kearney Sep 15 '09 at 17:12
  • 2
    It's also important to know that the bitwise operators like & and | operate on integers. The examples in this answer only work because `true` converts to `1` and `false` converts to `0`. If you had `echo ("cheese" & 4)` it would output zero, while `echo ("cheese" && 4)` would output true. – thomasrutter Jan 28 '14 at 03:34
15

I know your question is about understanding the bitwise operator and the accepted answer explains it well. But for the example you give, I cannot help but recommending you use the modulo operator instead:

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

Because it makes the intent clear that you are checking that the number is odd (not divisible by two), and it is more generic, so you can use ($var % 3) the same way and deduce how it works for any N.

alex
  • 479,566
  • 201
  • 878
  • 984
Pat
  • 36,282
  • 18
  • 72
  • 87
12

In addition to the other answers, it's worth noting that

if(func1() && func2())

Will only call func2() if func1() returns true ("lazy evaluation"), whereas

if(func1() & func2())

Will call both functions regardless, but the truth tables for both will be the same (assuming they return booleans).


thomasrutter points out (in the comments below) that you probably shouldn't do the latter in practice. (A & B) won't necessarily have the same truthiness as (A && B), particularly when A and B are integers. e.g., if A=1 and B=2 (both truthy), A & B will be falsey, whereas A && B is truthy. Also, another developer may think this is a typo and 'correct' it to two ampersands.

mpen
  • 272,448
  • 266
  • 850
  • 1,236
  • 1
    While this works *most of the time*, it won't always work, such as when the functions return numbers. Let's say func1() returns 1 and func2() returns 4. `func1() && func2()` will evaluate to `true` while `func1() & func2()` will evaluate to `0`. Even in the cases it does work, I wouldn't call it a good coding practice as it relies on side effects of evaluation order and of type conversion, making it harder to read and understand the purpose of the code. Any person reviewing the code might assume it's a typo. – thomasrutter Jan 28 '14 at 02:06