This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
Reference - What does this symbol mean in PHP?
I am working on some legacy code where I came across the following function:
function is_odd($number) {
return $number & 1; // 0 = even, 1 = odd
}
I have never seen a method to check if a number is odd written like that before and am just trying to understand what they actually are doing.
& is a bitwise-and, it basically works so that for every bit that is 1 in both operands, it yields 1 in the resulting value and 0 for all other bits. If you convert any number to its bit representation, you quickly see that it's the lowest bit that determines whether a number is even or odd, for example:
5 = 101
10 = 1010
13 = 1101
1030 = 10000000110
The lowest bit (the one on the very right, also called the least significant bit) is 1 for every odd number and 0 for every even number. Doing $n & 1 will always yield 0 for every other bit than the lowest bit (because the number 1 only has one bit, you can imagine that the rest of the bits are left-padded with 0 to match the length of the other operand). So basically the operation boils down to comparing the lowest bit of the operands, and 1 & 1 is 1, all other combinations are 0. So basically when the $n & 1 yields 1, it means the number is odd, otherwise it's even.
EDIT.
Here's a few examples to demonstrate how the bitwise-and works for the example values I gave earlier, the number in the parenthesis is the original decimal number:
101 (5)
& 001 (1)
---
001 (1) = true
1010 (10)
& 0001 (1)
----
0000 (0) = false
1101 (13)
& 0001 (1)
----
0001 (1) = true
10000000110 (1030)
& 00000000001 (1)
-----------
00000000000 (0) = false
From this you can easily see that the result is only true when both operands' right-most bits are 1.
Related
I am trying to decode a supposedly hex string. In MS SQL Server (11.0.2100) the data has the type of char(8).
In the manuals there was no clear way of decoding the data but it documents what it contains:
Given a hex string ie. 0001003F with a length of 4. The lower byte
is on the right, the higher byte is on the left. For each of the 4
'bytes' a reference table that maps a 'bit' to a certain truthy
value was given. A bit order is also given having the bit 0 or the bit
in right most being the 1st bit, ..., etc.
The table looks like this:
1st 'byte':
|Bit Order | Description | 1 | 0 | trigger |
|-----------|---------------|-------------------|-------------------|---------------|
|BIT0 | state foo | state foo is ON | State foo is OFF | high level |
|BIT1 | state bar | in state bar | not in state bar | high level |
| ...
|BIT7 | state bazz | in state bazz | not in state bazz | high level |
(3 more tables follows for the next 3 other 'byte's ..., each of the 4 'byte's supposedly has 8 equal number of 'bits')
I thought the way of decoding this data is to split the hex string into 4 parts and convert them into a binary string width a fixed with of 8.
In PHP, taken the example hex '0001003F', the first byte was '3F', having the converted to binary, 0011 1111 (space for clarity). Then, inferred that the value for the first byte was:
'state foo is on', 'in state bar', ..., 'not in state bazz'.
I also tried to do: hex2bin("0001003F") but it outputs strin(4) " # ".
Is this the correct way of decoding this data?
(I beg your pardon if the tags are incorrect.)
Since 4 bytes fit into the storage for integer type on almost all platforms (32-bit and higher), you can convert the hex string to integer, then use the bitwise operators to check if specific bit is set:
$hex_str = '0001003F';
$flags = base_convert($hex_str, 16, 10);
foreach (range(0, 31) as $bit) {
printf("Bit %d: %d\n", $bit, (bool) ($flags & (1 << $bit)));
}
Output
Bit 0: 1
Bit 1: 1
Bit 2: 1
Bit 3: 1
Bit 4: 1
Bit 5: 1
Bit 6: 0
...
Bit 15: 0
Bit 16: 1
Bit 17: 0
...
Bit 31: 0
If bit $bit is set (1), then the state corresponding to this bit is on.
The code converts the hex string $hex_str to an integer $flags with the help of base_convert function. The loop iterates bit numbers in range [0;31] (starting from the least significant bit). The (1 << $bit) expression is the value 1 shifted to the left by $bit bits. Thus, if bit number $bit is set, then the result of the bitwise AND operation is a non-zero integer. The result is cast to boolean type to produce 1, if the result is non-zero, and 0 otherwise.
It is easy to see that you can test a number of bits with a single bitwise AND operation, e.g.:
// Check if at least one of three bits is set, 3rd, 10th, or 11th
$mask = (1 << 3) | (1 << 10) | (1 << 11);
if ($flags & $mask)
printf("At least one of the bits from mask 0x%x is set\n", $mask);
Output
At least one of the bits from mask 0xc08 is set
This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
Reference - What does this symbol mean in PHP?
I am trying to learn PHP and programming.
In the book I am studying there is something like:
$flags = PREG_SPLIT_NO_EMPTY | PREG_SPLIT_DELIM_CAPTURE;
$flags is used for the split() method.
The first flag is: If this flag is set, only non-empty pieces will be returned by preg_split().
The second is: If this flag is set, parenthesized expression in the delimiter pattern will be captured and returned as well.
Why isn't he using && operator but the | ?
Can you please explain what | does actually?
As far as I know these are
&& is the logical AND whereas | is a bitwise operator.
a && b evalutes to true when both operands are evaluted to true. Since flags are almost always numbers greater than 1, this expression always evalutes to true.
How functions accepting bitmasks work
They specify constants
Note that these constants have to have powers of 2:
FLAG_INT1 = 1
FLAG_INT2 = 2
FLAG_INT3 = 4
FLAG_INT4 = 8
You call the function combining some flags
myFunction(FLAG_INT1 | FLAG_INT3)
This leads to a bitwise OR operation:
0001
OR 0100
=======
0101
A set bit (1) in one (or both) of the operands will lead to a set bit (1) in the result, too.
The function checks internally for each flag
This requires a bitwise AND operation:
0101
AND 0001 // check for FLAG_INT1
========
0001 // true
0101
AND 0010 // check for FLAG_INT2
========
0000 // false
0101
AND 0100 // check for FLAG_INT3
========
0100 // true
The bitwise AND required both operands to have a set bit (1) at position X in order to result in a set bit (1) in the result at position X.
Wikipedia has also a nice article about the common bitwise operators: http://en.wikipedia.org/wiki/Bitwise_operation
&& is the Logical "AND"
but the | is a bitwise
Looking at some code written by another developer, I came across this:
for($i=1; $i<=30; $i++)
{
if($i&1)
$color = '#fff';
else
$color = '#bbb';
}
This $color variable is used for row background colour later in the code. The alternating colours work fine.
If I was writing this, I would have used the modulus operator (%) rather than the bitwise (&) operator.
Why does the bitwise operator work in this case? Is there any advantage of using this method rather than the modulus operator?
The & operator does a bitwise comparison on the number. So if you do
$i & 1
it will then tell you if the '1' flag is set, such as in binary:
001010111010
The last number is the '1' flag (remember, binary goes 1, 2, 4, 8 etc. in reverse order), which in this case is set to 0.
Since 1 is the only odd flag in binary, it will tell you if the number is odd or even.
if $i is 3 for example, then in binary it will be 011 - the last number is a 1 (the 1 flag) and thus $i & 1 will be true.
if $i is 4 for example, then in binary it will be 100 - the last number is a 0 (the 1 flag) and thus $i & 1 will be false.
It works because the first bit is always 1 if the number is odd and 0 if the number is even.
1
10
11
100
101
110
111
etc.
In theory bitwise operation is faster than the modulus operation, but it's possible that the interpreter would have optimized the modulus operation down to bitwise operation anyway.
Why the other developer used it, we can only guess: out of habit, copy-pasted from somewhere, doesn't know about the modulus operator, showing off, wanting to optimize...
The variables values are listed below
$v['flag'] = 10
kPOSTAGE_HOME = 8
So what the heck does the following line do?!
if(($v['flag']&kPOSTAGE_HOME)==kPOSTAGE_HOME) {
//do something
}
& sets the bits set on both values. Some binary maths:
00001010 | 10
& 00001000 | 8
---------------
= 00001000 | 8
So 10&8 returns 8, and 8==8. Reason is to check whether a flag in that bit mask is set ...
It checks whether the bit-pattern in $v['flag'] has it's 3rd bit set.
And, for better readability, it can be simplified to the following:
if ( $v['flag'] & kPOSTAGE_HOME ) {
It's masking the '8' bit in the variable. The number '10' in base 10 == 1001 in binary, and 8 == 1000. So this means "does 1001 have the 1000" bit set?" The answer is 'yes'.
It checks whenever third bit is on in $v['flag'].
The & is "bitwise and" operator, binary of 8 is "00000100", therefore then you will do "bitwise and" all bits except the third will be zero, so in case third bit is on it will remains, therefore you have further check for equality.
What does this code mean and what are other ways accomplish the same without using bit shifting?
if ($n & ($n - 1))
That formula checks to see whether a number is a power of 2 (if your condition as written is true, then the number is not a power of two).
Stated another way, your test checks to see whether there is more than one "1" bit set in the binary representation of $n. If there is zero or only one bit set, then your test will be false.
It is by far the most efficient way to determine that property.
First, this code is valid PHP, so your title is poor.
Second, the binary arithmetic going on looks something like this:
42 = 101010
&
41 = 101001
-----------
40 = 101000
Like Greg states this is the fastest way to check for a power of 2 number, but the code you've given checks to see if the number is not a power of 2. This can easily be ascertained by PHP's policy of: any non-null/non-zero value is true.
When we use ($n & ($n - 1)) then it converts $n & ($n-1) to its binary values and does binary AND operation.
Example
3 = 0011
4 = 0100
5 = 0101
3 = 0011
&
4 = 0100
------------
0
4 = 0100
&
5 = 0101
-----------
100
To check if given number is power of 2 or not we alway use formulae
($n & ($n - 1) == 0) which means ANDing of $n & $n-1 is equals to 0 or not.
Online AND Operation Calculator