When should I use a bitwise operator? - php

I read the following Stack Overflow questions, and I understand the differences between bitwise and logical.
Difference between & and && in PHP
Reference - What does this symbol mean in PHP?
However, none of them explains when I should use bitwise or logical.
When should I use bitwise operators rather than logical ones and vice versa?
In which situation do I need to compare bit by bit?
I am not asking about the differences, but I am asking the situation when you need to use bitwise operators.

Bitwise is useful for things in PHP just like anything else.
How about a value that can have multiple states turned on at the same time?
<?php
// since we're setting constant values in base10 we must progressively double
// them since bitwise operations work in base2. you'll see why when we output
// these as binary values below.
const STATE_FOO = 1;
const STATE_BAR = 2;
const STATE_FEZ = 4;
const STATE_BAZ = 8;
// show base2 values of the above constants
echo sprintf("STATE_FOO's base2 value is %08d\n", decbin(STATE_FOO));
echo sprintf("STATE_BAR's base2 value is %08d\n", decbin(STATE_BAR));
echo sprintf("STATE_FEZ's base2 value is %08d\n", decbin(STATE_FEZ));
echo sprintf("STATE_BAZ's base2 value is %08d\n\n", decbin(STATE_BAZ));
// set state to FOO and FEZ
$state = STATE_FOO | STATE_FEZ;
echo sprintf("base10 value of \$state is %s\n", $state);
echo sprintf("base2 value of \$state is %08d\n", decbin($state));
echo sprintf("Does \$state include FOO state? %s\n", (bool)($state & STATE_FOO));
echo sprintf("Does \$state include BAR state? %s\n", (bool)($state & STATE_BAR));
echo sprintf("Does \$state include FEZ state? %s\n", (bool)($state & STATE_FEZ));
echo sprintf("Does \$state include BAZ state? %s\n", (bool)($state & STATE_BAZ));
echo sprintf("Is state equivalent to FOO and FEZ states? %s\n", ($state == (STATE_FOO | STATE_FEZ)));
Output:
STATE_FOO's base2 value is 00000001
STATE_BAR's base2 value is 00000010
STATE_FEZ's base2 value is 00000100
STATE_BAZ's base2 value is 00001000
base10 value of $state is 5
base2 value of $state is 00000101
Does $state include FOO state? 1
Does $state include BAR state?
Does $state include FEZ state? 1
Does $state include BAZ state?
Is state equivalent to FOO and FEZ states? 1

Forget what is already in your head.
OK, now say you have some different roles: admin, user, and guest.
and some different permissions: read, write and delete
Let's create some bitmasks for permissions and roles. A bitmask is a sequence of bits that can be used to manipulate or read some kind of flags. As shown below:
// flags bitmasks
$read = 1; // 0001
$write = 2; // 0010
$delete = 4; // 0100
$admin = $read | $write | $delete; // 0001 | 0010 | 0100 => 0111
$user = $read | $write; // 0001 | 0010 => 0011
$guest = $read; // 0001 => 0001
Notice 1, 2, 4. This must be raised as double. Otherwise, it might give you some awkward results.
Forget about the things commented. Those are just sequence of bits (or bitmasks) for individual permissions and roles.
Now let's create a handy function which may be used to check a specific permission for a specific role.
function isAllowed($role, $permissison) {
return $role & $permissison ? true : false;
}
We are done. Let's check the $delete permission for all 3 roles:
var_dump(isAllowed($admin, $delete)); // bool(true)
var_dump(isAllowed($user, $delete)); // bool(false)
var_dump(isAllowed($guest, $delete)); // bool(false)
So why is bitwise operation? In a word, bitwise operation is more faster, concise and maintainable. Otherwise, using bitwise operation is always efficient for complex applications.

Bitwise | and & and logical || and && are totally different.
Bitwise operators perform operations on the bits of two numbers and return the result. That means it's not a yes or no thing. If they're being used in conditional statements, they're often used as part of logical comparisons. For example:
if ($x & 2 == 2) {
// The 2^1 bit is set in the number $x
}
Logical operators compare two (or more) conditions/expressions and return true or false. You use them most commonly in conditional statements, like if and while. For example:
if ($either_this || $or_this) {
// Either expression was true
}

Bitwise operators are specifically used in case of binary value representation.
echo '0110011010' & '0101001001';
//0100001000
Logical operators are most preferred for comparison and are a bit faster than bitwise operator in case of AND and XOR operations.
if(func1() && func2())
if func1() returns false it won't bother calling func2()
if(func1() & func2())
Will call both functions regardless of their returned values.

In most cases, you'll probably want to use logical operators. They're used for combining logical conditions, generally to control program flow, e.g. ($isAlive && $wantsToEat).
Bitwise operators are used when you want to perform operations on a bit-by-bit basis on the underlying binary representations of integers. e.g. (5 & 3) == 7. As others have suggested, there's usually not a lot of call for this in the sort of application that tends to get written in PHP (although there is in lower-level languages, like C).

Bitwise operators are useful when manipulating the bits of a number. Look here. Otherwise you should use the logical operators. Also the logical operators are short-circuited. For example, if you have a && b and a is false, b is not evaluated.
Disclaimer: I am coming from a Java background, but I guess in PHP it is the same.

They are two very different operators.
When you want two conditions to simultaneously be true, you use the logical &&. For example, I want to print out "happy birthday" only if the person's birthday is today && they have money in the account. This is used whenever we want to perform composition of two or more conditions, mostly in if statements and loop conditions (although not exclusively).
When you want to perform bitwise operations (which in day-to-day PHP programming is much more rare), you use the bitwise &. This is far more rare, and you might be performing bitwise masking (I doubt it though), so you might only want a result that both integers represent, in which case you can say newAttribute = attribute1 & attribute2;.

Well, asuming there is $x = (false && some_function());, here the value of $x will be set without calling the some_function() because the first value was FALSE.
But what if you needed to call that function anyway? Use $x = (false & some_function());.
In other words, the & uses MORE processing than the &&, just because && does not run through all the values to check them. If it found one value as false, it would return it, not looking at other values.
And in logical operations, use the && operator as it's used to return the logical operation value, where & is used to set a value and in an if statement it will always return true.

Related

What is the purpose of XOR with zero

Taken from here: http://php.net/manual/en/function.base-convert.php#105414
function rome($N){
$c='IVXLCDM';
for($a=5,$b=$s='';$N;$b++,$a^=7)
for($o=$N%$a,$N=$N/$a^0;$o--;$s=$c[$o>2?$b+$N-($N&=-2)+$o=1:$b].$s);
return $s;
}
What is the purpose of XOR $a^0; here? (4th line)
Deleting it doesn't seem to make any difference. Check it out at: http://goo.gl/K6TwQI
You'll commonly see people use bitwise operators to implicitly convert expressions to an integer because of the way the underlying language works. This is mainly because these operations are blazing fast and avoid function calls, etc.
Because XOR doesn't affect the integer part of the variable, my best best is that this is just being used to ensure $a is always evaluated as an integer.
Here's an example.

Bitwise comparison in PHP

I confess I don't really know what I'm doing! I'm pulling some data from SecondLife and parsing it in PHP. The data is an integer from llGetRegionFlags which, in my case, returns 1048592
Now I need to do a bitwise comparison in PHP to figure out which flags are true/false. For example 0x00000040 is used for the "block terraform" flag.
The notations are in hex for each flag, and I have an integer to test against, and the PHP manual suggests integers and shows examples in binary.
So my question really is, given an integer and some hex flags, how do I go about doing the bitwise comparison in PHP? Brainfried! Thanks in advance
To determine if a particular bit is turned on, use the & (AND) operator:
if ($data & 0x00000040) {
// block terraform flag is true
}
If the bit is turned on, the AND operator will return a positive number. If it is turned off, then the AND operator will result in a zero.
Use a single AND & / OR |
if ($value1 & $value2) { }
The PHP Manual explains more: http://php.net/manual/en/language.operators.bitwise.php
You could define the bits required, and check against them to make it look clean. ie
define('BLOCK_TERAFORM', 0x00000040);
....
if($data & BLOCK_TERAFORM) {
... do something ...
}
Usually the bitflags are checked with a piece of code like this:
$blockTerraformFlag = 0x00000040;
$isBlockTerraform = (($RegionFlags & $blockTerraformFlag) == $blockTerraformFlag);

PHP debug_backtrace bitmask usage

Trying to understand this entry in the php manual on debug_backtrace.
I don't understand what they mean by "this parameter is a bitmask for ...."
I have done web searches on bitmasks and my head is spinning round so I have decided I don't really want to learn the detail about it but just to know how I can supposed to add the options to that function.
Do I put in both options as in
debug_backtrace(DEBUG_BACKTRACE_PROVIDE_OBJECT, DEBUG_BACKTRACE_IGNORE_ARGS)
if I want both and one of them if I only want that one?
Be aware that those 2 constants (DEBUG_BACKTRACE_PROVIDE_OBJECT, DEBUG_BACKTRACE_IGNORE_ARGS) are different in meaning. While DEBUG_BACKTRACE_PROVIDE_OBJECT provides an additional object when present, DEBUG_BACKTRACE_IGNORE_ARGS strips the args when present.
Since the most common use-case for these constants is to reduce memory usage, the way with least memory-consumption is:
debug_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS);
NOT
// false friend!
debug_backtrace(DEBUG_BACKTRACE_PROVIDE_OBJECT | DEBUG_BACKTRACE_IGNORE_ARGS);
It overrides the default of DEBUG_BACKTRACE_PROVIDE_OBJECT and additionally ignores DEBUG_BACKTRACE_IGNORE_ARGS.
The constants will have values of 2^n in decimal, or (10)^n in binary. For example - 1, 10, 100, 1000, etc (in binary).
Say a=001, b=010, c=100:
You can do bitwise or on, for example, a and b. This will mean each bit will be 'turned on' if the same bit in either a or b is 'on'.
a | b == 011
This is a bitmask. The bitmask is checked for the inclusion of a by
bitmask & a != 0
Which is
011 & 001 == 001 != 0
However, because c is not in the bitmask:
bitmask & c == 011 & 100 == 0
So, to include both a and b in the bitmask, you use the binary or operator.
debug_backtrace(DEBUG_BACKTRACE_PROVIDE_OBJECT | DEBUG_BACKTRACE_IGNORE_ARGS);
It means you combine options with the bitwise OR operator: |.
For example:
debug_backtrace(DEBUG_BACKTRACE_PROVIDE_OBJECT | DEBUG_BACKTRACE_IGNORE_ARGS);
For more details about bitmasks: http://en.wikipedia.org/wiki/Mask_(computing)

bitmask type of argument in javascript

I see that in PHP there are functions that can accept multiple options into a single argument, for example:
error_reporting(E_ERROR & E_WARNING);
I want to implement this kind of functionality into my javascript function. Do you know examples of functions that take this kind of arguments?
I'm totally confused about how does the function know what are the options that are passed...
(Assume it is instead: error_reporting(E_ERROR | E_WARNING); )
Well, it is a bitmask. So E_ERROR might be a number like this (in binary):
0010000
and E_WARNING might be:
0000010
and when they are combined with |, you get
0010010
(a single integer, with multiple bits set)
The function can then check which bits are set using the & bitwise operator. You can certainly do it in javascript, although it might be less common, and possibly less efficient and reliable as the numbers get bigger since javascript doesn't really have integers, they are really floating point numbers.
In javascript, you might prefer to use something like this:
error_reporting({warning: true, error: true});
(edited to show it in the more sensible way, with | not & to combine them)
Yes, it's possible, but it works with |.
var flag1 = 1,
flag2 = 2; // powers of 2
function get(flags) {
if((flags & flag1) === flag1) { // remove all other bits and check
alert('flag1'); // whether you get the flag itself
}
if((flags & flag2) === flag2) {
alert('flag2');
}
}
get(flag1 | flag2); // alerts both
You could of course create a helper function which does the chekcing so that you don't need those parentheses:
function contains(flags, flag) {
return (flags & flag) === flag;
}
http://jsfiddle.net/pimvdb/NpFYj/1/

Understanding PHP & (ampersand, bitwise and) operator

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?
& 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.
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.
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
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.
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.

Categories