Delicious Bookmark this on Delicious Share on Facebook SlashdotSlashdot It! Digg! Digg



PHP : Language Reference : Operators : Bitwise Operators

Bitwise Operators

Bitwise operators allow you to turn specific bits within an integer on or off. If both the left- and right-hand parameters are strings, the bitwise operator will operate on the characters' ASCII values.

<?php
echo 12 ^ 9; // Outputs '5'

echo "12" ^ "9"; // Outputs the Backspace character (ascii 8)
// ('1' (ascii 49)) ^ ('9' (ascii 57)) = #8

echo "hallo" ^ "hello"; // Outputs the ascii values #0 #4 #0 #0 #0
// 'a' ^ 'e' = #4
?>

Table6.3.Bitwise Operators

Example Name Result
$a & $b And Bits that are set in both $a and $b are set.
$a | $b Or Bits that are set in either $a or $b are set.
$a ^ $b Xor Bits that are set in $a or $b but not both are set.
~ $a Not Bits that are set in $a are not set, and vice versa.
$a << $b Shift left Shift the bits of $a $b steps to the left (each step means "multiply by two")
$a >> $b Shift right Shift the bits of $a $b steps to the right (each step means "divide by two")


Warning:

Don't right shift for more than 32 bits on 32 bits systems. Don't left shift in case it results to number longer than 32 bits.

Code Examples / Notes » language.operators.bitwise

27-apr-2006 08:31

[Editors note: This is not true. You will have to check every possible combination, for instance: $a = array(); $b = ""; $c = null; $d = 0; will print "not equal" but if you set $b = null and $c = "" it will print "equal"]
For the sake of completeness I want to note that a check for equality doesn't have so long winded as in the (wrong) example below. Because of simple laws of logic you don't have to check every possible combination of the variables. The following code will be no surprise for most of you, but for some people it could be helpful.
-Tim
<?php
$a = 42 ;
$b = 42 ;
$c = 1138 ;
$d = 1701 ;
echo $a==$b && $b==$c && $c==$d ? "equal" : "not equal" ; // echoes not equal
$a = 42 ;
$b = 42 ;
$c = 42 ;
$d = 42 ;
echo $a==$b && $b==$c && $c==$d ? "equal" : "not equal" ; // echoes equal
?>


rob

Well, every programmer already knows this but for anyone new to the fun here's some quick clean code to determine if a number is odd or even.
function oddeven($x){
if($x & 1) return "odd";
else return "even";
}


visual

To perform bitwise operations on floats, or anything for that matter, in the binary representation of your choice, simply use pack() on the data with the appropriate parameters, then you can operate on the resulting strings. in the end just unpack()

xert

To determine number of bits set to 1 use:
<?php
function bits($val)
{
   $v = (int)$val;
   $c = 0;
   for ($c=0; $v; $c++)
   {
       $v &= $v - 1;
   }
   return $c;
}
?>
Code from: http://graphics.stanford.edu/~seander/bithacks.html


dasch

The function below can be rewritten to this:
<?php
function setflag (&$var, $flag, $set = true)
{
  $var = $set ? ($var | $flag) : ($var & ~$flag);
}
?>


rizal dot almashoor

The following function will perform a 32-bit left shift on a 64-bit machine:
<?php
function leftshift32($number, $steps)
{
$binary = decbin($number).str_repeat("0", $steps);
$binary = str_pad($binary, 32, "0", STR_PAD_LEFT);
$binary = substr($binary, strlen($binary) - 32);
return $binary{0} == "1" ? -(pow(2, 31) - bindec(substr($binary, 1))) : bindec($binary);
}
?>


sgarner

The bitwise AND operator behaves oddly inside an IF statement when used with equal arguments.
<?php
echo 9 & 8;
// outputs '8' (correct)
echo 8 & 8;
// outputs '8' (correct)
if (9 & 8 == 8) echo 'true'; else echo 'false';
// outputs 'true' (correct)
if (8 & 8 == 8) echo 'true'; else echo 'false';
// outputs 'false' (wrong!!)
?>
The solution is to add parentheses:
<?php
if ((8 & 8) == 8) echo 'true'; else echo 'false';
// outputs 'true' (correct)
?>
Tested on PHP 5.2.1


jbrand1

So here's an interesting little thing that I do with bitwise operators, could potentially be useful to others.
I have a roles based system which shows, among other things, menu entries based on a users role. The menu entries are stored in a mysql database as are the users and the roles.
My users table looks like this:
+----------+--------+
| Username | RoleID |
+----------+--------+
| admin    |      1 |
| suser     |      2 |
|  user     |      4 |
+----------+--------+
My roles table looks like this:
+-------------------------------+--------+
| RoleName                      | RoleID |
+-------------------------------+--------+
| System Administrator          |      1 |
| Super User                    |      2 |
| User                           |      4 |
+-------------------------------+--------+
My menus table looks like this:
+-------------------+---------------------+---------+
| Menu_Title         | MenuFile            |  Roles  |
+-------------------+---------------------+---------+
| Data              | Data.php            |      7   |
| All Data           | All_Data.php         |      3   |
| Shutdown          | Shutdown.php         |      1   |
+-------------------+---------------------+---------+
Now, when the user logs in I run a select to see if they are valid:
SELECT * FROM Users WHERE Username = '<USER>' AND Password = '<PW>'
If no rows were returned I print an error message and redraw the login screen, otherwise I set some session variables:
<?php
  $row = mysql_fetch_assoc($recordset);
  $_SESSION['Username'] = $row['Username'];
  $_SESSION['RoleID'] = $row['RoleID'];
?>
In my MainMenu.php I check that a valid user is logged in and if so I generate the menu:
<?php
  if( isset($_SESSION['Username']) &&
      isset($_SESSION['RoleID']) )  
  {
       generateMenuEntries($_SESSION['RoleID']);
  }
?>
<?php
 /********************************************/
/** Generates the menu                                             */
/*******************************************/
function generateMenuEntries( $roleID )
{
     $menuQuery = sprintf("SELECT * FROM menus WHERE (Roles & %d) = %d", $roleID, $roleID);
     $menuRecordset = mysql_query($menuQuery, $myConn);
     
     while( $menu = mysql_fetch_assoc( $menuRecordset ))
     {
        echo '    <tr>';
        echo '      <td width="3%">&nbsp;</td> ';
        echo '      <td width="97%"><a href="'; echo $menu['MenuFile']; echo '">'; echo $items['Menu_Title']; echo '</a></td>';
        echo '    </tr>';
     }
}
?>
So the important part of the query is the (Roles & $roleID) = $roleID, that does a bitwise AND function and since only one bit is set in our role the value returned will either be 0 or the $roleID.  
I know this isn't the most secure way to handle the user/session data but it's sufficient for my needs.  I have to be careful when I add roles so that it's 2^whatever.   I wish I knew how to change the auto_increment so that it was just a bit shift.  I suppose I could use an auto-generated  ID field and do a stored procedure that calculates the role as 2^ID. I'll have to look into it.
Hope this helps someone.


redduck666

since i have no idea how do we get:
echo 12 ^ 9; // Outputs '5'
i searched for another tutorial, and this is what i found http://www.litfuel.net/tutorials/bitwise.htm, hopefully someone will find this useful ;)


icy

Say... you really want to have say... more than 31 bits available to you in your happy bitmask. And you don't want to use floats. So, one solution would to have an array of bitmasks, that are accessed through some kind of interface.
Here is my solution for this: A class to store an array of integers being the bitmasks. It can hold up to 66571993087 bits, and frees up unused bitmasks when there are no bits being stored in them.
<?php
/*
Infinite* bits and bit handling in general.

*Not infinite, sorry.

Perceivably, the only limit to the bitmask class in storing bits would be
the maximum limit of the index number, on 32 bit integer systems 2^31 - 1,
so 2^31 * 31 - 1 = 66571993087 bits, assuming floats are 64 bit or something.
I'm sure that's enough enough bits for anything.. I hope :D.
*/
DEFINE('INTEGER_LENGTH',31); // Stupid signed bit.
class bitmask
{
protected $bitmask = array();

public function set( $bit ) // Set some bit
{
$key = (int) ($bit / INTEGER_LENGTH);
$bit = (int) fmod($bit,INTEGER_LENGTH);
$this->bitmask[$key] |= 1 << $bit;
}

public function remove( $bit ) // Remove some bit
{
$key = (int) ($bit / INTEGER_LENGTH);
$bit = (int) fmod($bit,INTEGER_LENGTH);
$this->bitmask[$key] &= ~ (1 << $bit);
if(!$this->bitmask[$key])
unset($this->bitmask[$key]);
}

public function toggle( $bit ) // Toggle some bit
{
$key = (int) ($bit / INTEGER_LENGTH);
$bit = (int) fmod($bit,INTEGER_LENGTH);
$this->bitmask[$key] ^= 1 << $bit;
if(!$this->bitmask[$key])
unset($this->bitmask[$key]);
}

public function read( $bit ) // Read some bit
{
$key = (int) ($bit / INTEGER_LENGTH);
$bit = (int) fmod($bit,INTEGER_LENGTH);
return $this->bitmask[$key] & (1 << $bit);
}
public function stringin($string) // Read a string of bits that can be up to the maximum amount of bits long.
{
$this->bitmask = array();
$array = str_split( strrev($string), INTEGER_LENGTH );
foreach( $array as $key => $value )
{
if($value = bindec(strrev($value)))
$this->bitmask[$key] = $value;
}
}
public function stringout() // Print out a string of your nice little bits
{
$string = "";
$keys = array_keys($this->bitmask);
sort($keys, SORT_NUMERIC);
for($i = array_pop($keys);$i >= 0;$i--)
{
if($this->bitmask[$i])
$string .= sprintf("%0" . INTEGER_LENGTH . "b",$this->bitmask[$i]);
}
return $string;
}

public function clear() // Purge!
{
$this->bitmask = array();
}

public function debug() // See what's going on in your bitmask array
{
var_dump($this->bitmask);
}
}
?>
It treats a positive integer input as a bit, so you don't have to deal with the powers of 2 yourself.
<?php
$bitmask = new bitmask();
$bitmask->set(8979879); // Whatever
$bitmask->set(888);
if($bitmask->read(888))
print 'Happy!\n';
$bitmask->toggle(39393); // Yadda yadda
$bitmask->remove(888);
$bitmask->debug();
$bitmask->stringin("100101000101001000101010010101010
00000001000001");
print $bitmask->stringout() . "\n";
$bitmask->debug();
$bitmask->clear();
$bitmask->debug();
?>
Would produce:
Happy!
array(2) {
 [289673]=>
 int(65536)
 [1270]=>
 int(8388608)
}
0000000000000001001010001010010001010100101010100
0000001000001
array(2) {
 [0]=>
 int(355106881)
 [1]=>
 int(37970)
}
array(0) {
}


alexrussell101

re the 12 ^ 9 = 5 comment, the link doesn't seem to work but here's the explanation (although if you're dealing with bitwise operators you really should get this):
12 in binary is 1100
9 in binary is 1001
If you XOR (the ^ operator) these two binary values you get the binary value 0101 (101) which is 5 in decimal. It's that simple.


crizza

Personally I get a great deal of pleasure using bitwise operators for dealing with flags
here is an example using c code because im a php noob, but the principal of bitwise ops is the same.
#define F_WITH_DEBUG  0x01
#define F_WITH_HELP_INFO 0x02
#define F_BE_VERBOSE   0x04
unsigned short flags = 0;
flags |= ( F_WITH_DEBUG | F_WITH_HELP_INFO | F_BE_VERBOSE );
/* now the first byte of flags look like this 00000111 */
/* check the status of flags */
if( flags & F_WITH_DEBUG) {

/* do something */
}
flags are great, I love *them.


eric swanson

Perl vs. PHP implementation of the ^ operator:
After attempting to translate a Perl module into PHP, I realized that Perl's implementation of the ^ operator is different than the PHP implementation.  By default, Perl treats the variables as floats and PHP as integers.  I was able to verify the PHP use of the operator by stating "use integer;" within the Perl module, which output the exact same result as PHP was using.
The logical decision would be to cast every variable as (float) when using the ^ operator in PHP.  However, this will not yield the same results.  After about a half hour of banging my head against the wall, I discovered a gem and wrote a function using the binary-decimal conversions in PHP.
/*
not having much experience with bitwise operations, I cannot tell you that this is the BEST solution, but it certainly is a solution that finally works and always returns the EXACT same result Perl provides.
*/
function binxor($a, $b) {
   return bindec(decbin((float)$a ^ (float)$b));
}
//normal PHP code will not yeild the same result as Perl
$result = 3851235679 ^ 43814; //= -443704711
//to get the same result as Perl
$result = binxor(3851235679, 43814); //= 3851262585
//YIPPEE!!!
//to see the differences, try the following
$a = 3851235679 XOR 43814;
$b = 3851235679 ^ 43814; //integer result
$c = (float)3851235679 ^ (float)43814; //same as $b
$d = binxor(3851235679, 43814); //same as Perl!!
echo("A: $a<br />");
echo("B: $b<br />");
echo("C: $c<br />");
echo("D: $d<br />");


louis /at/ mulliemedia.com

Note that the ^ operator, unlike in some other languages, is *not* the same as the pow() function.

tbrendstrup

note that the shift operators are arithmetic, not logic like in C. You may get unexpected results with negative numbers, see http://en.wikipedia.org/wiki/Bitwise_operation
here's a function to do logic right shifts.
<?php
function lshiftright($var,$amt)
{
$mask = 0x40000000;
if($var < 0)
{
$var &= 0x7FFFFFFF;
$mask = $mask >> ($amt-1);
return ($var >> $amt) | $mask;
}
return $var >> $amt;
}
$val = -10;
printf("arithmetic shift on a negative integer
%1\$032b
%2\$032b
%1\$0d
%2\$0d
",$val, $val >> 1 );
printf("logic shift on a negative integer
%1\$032b
%2\$032b
%1\$0d
%2\$0d
",$val, lshiftright($val, 1));
printf("logic shift on a positive integer
%1\$032b
%2\$032b
%1\$0d
%2\$0d
",-$val, lshiftright(-$val, 1));
?>
gives the output:
arithmetic shift on a negative integer
11111111111111111111111111110110
11111111111111111111111111111011
-10
-5
logic shift on a negative integer
11111111111111111111111111110110
01111111111111111111111111111011
-10
2147483643
logic shift on a positive integer
00000000000000000000000000001010
00000000000000000000000000000101
10
5


tanstep

Note that precedence is wrong for bitwise and comparison operators:
use this:
   if((pow(2, $pos) & $_bits) > 0)
NOT this:
   if(pow(2, $pos) & $_bits > 0)


planev ea2005#planev.com

My very simple bit functions:
setbit($bits,$bit)
getbit($bits,$bit)
unsetbit($bits,$bit)
function setbit($bits,$i){

if (($i <= strlen($bits)-1) && ($i >= 0)) {
 $bits[strlen($bits)-1-$i] = "1";
}
return $bits;  
}
function unsetbit($bits,$i){

if (($i <= strlen($bits)-1) && ($i >= 0)) {
 $bits[strlen($bits)-1-$i] = "0";
}
return $bits;  
}
function getbit($bits,$i){

if (($i <= strlen($bits)-1) && ($i >= 0)) {
 $bit = $bits[strlen($bits)-1-$i];
}
return $bit;
}


zewt

if you use bitwise you MUST make sure your variables are integers, otherwise you can get incorrect results.
I recommend ALWAYS
(int)$var & (int)$var2
This will save you many headaches when troubleshooting a completely illogical result.


junk

I wanted to print a binary representation of an integer here it is
<?php
function binString($var, $safety = 0) {
return ($var & 1) . ($var != 0 && $safety < 31 ? binString($var >> 1, $safety+1) : "");
}
print binString(5); // would print 101
print binString(15); // would print 1111
?>
Explanation:
the first expression after the return statement will evaluate to 1 or 0 according to the least significant bit.
then we have our stop condition if there is still non zero bits left or if we are at the 32nd bit otherwise we call recursively on to the n-1 bits (by shifting out the least significant bit).


zlel grxnslxves13

I refer to Eric Swanson's post on Perl VS PHP's implementation of xor.
Actually, this is not an issue with the implementation of XOR,  but a lot more to do with the lose-typing policy that PHP adopts.
Freely switching between int and float is good for most cases, but problems happen when your value is near the word size of your machine. Which is to say, 32-bit machines will encounter problems with values that hover around 0x80000000 - primarily because PHP does not support unsigned integers.
using bindec/decbin would address this issue as a work-around to do unsigned-int xor, but here's the real picture (i'm not claiming that this code will perform better, but this would be a better pedagogical code):
<?php
function unsigned_xor32 ($a, $b)
{
       $a1 = $a & 0x7FFF0000;
       $a2 = $a & 0x0000FFFF;
       $a3 = $a & 0x80000000;
       $b1 = $b & 0x7FFF0000;
       $b2 = $b & 0x0000FFFF;
       $b3 = $b & 0x80000000;
       $c = ($a3 != $b3) ? 0x80000000 : 0;
       return (($a1 ^ $b1) |($a2 ^ $b2)) + $c;
}
$x = 3851235679;
$y = 43814;
echo "
This is the value we want";
echo "
3851262585";
echo "
The result of a native xor operation on integer values is treated as a signed integer";
echo "
".($x ^ $y);
echo "
We therefore perform the MSB separately";
echo "
".unsigned_xor32($x, $y);
?>
This is really foundation stuff, but for those of you who missed this in college, there seems to be something on 2's complement here:
http://www.evergreen.edu/biophysics/technotes/program/2s_comp.htm


kendsnyder

I needed to perform a bitwise AND on floats and came up with this.  There is probably a better way to do this with bit rotation, but this works.
/**
* Perform a float-safe bitwise AND comparison
*
* @param int/float $number  The number to which to perform a bitwise AND
* @param int/float $comparison  The number with which to perform a bitwise AND
* @return bool
*/
function safeBitCheck($number,$comparison) {
   if( $number < 2147483647 ) {
       return ($number & $comparison)==$comparison;  
   } else {
       $binNumber = strrev(base_convert($number,10,2));
       $binComparison = strrev(base_convert($comparison,10,2));
       for( $i=0; $i<strlen($binComparison); $i++ ) {
           if( strlen($binNumber)<$i || ($binComparison{$i}==="1" && $binNumber{$i}==="0") ) {
               return false;  
           }
       }
       return true;
   }
}
safeBitCheck(17,16); // true
safeBitCheck(17,2); // false
safeBitCheck((4294967296+8589934592),4294967296); // true
safeBitCheck(2,8589934592); // false


bryanagee

I found the 31-bit limitation on the bitwise ands to be a bit frustrating in large scale permission control applications. I have a situation involving page-level access with more than 50 pages. I was able to workaround the limitation by adding a loop that dropped 31 bits off of the right until the resource identifier bit is within the first 31.
<?php
       $userlevel = $session->userlevel - 0;  # the subtraction ensures int type
       $pg_code = pow(2,($pg_id-1));
       
       while ($pg_code >= 2147483648)  {
               $pg_code =  $pg_code/pow(2,31);
               $userlevel = $session->userlevel/pow(2,31) ;
       }
       if (!($userlevel - 0 & $pg_code)) {
               #if not authorized, show the unauthorized page
               header('Location: Unauthorized.php');
               exit;
       }
?>


krang

Hopefully this may help someone understand the fun of Bitwise Operators....
The purpose of this function is to return a value from the GPC (Get, Post and Cookie) and do some basic formatting to it depending on the $VALIDATION value:
<?PHP
 function RETURN_SUBMITTED_VALUE ($VARIABLE, $METHOD, $VALIDATION) {
  //-------------------------------
  // Get the value from the
  // relevant submit method...
      if ($METHOD == 'POST') {
        if (!isset($_POST[$VARIABLE])) $_POST[$VARIABLE] = '';
        $VALUE = $_POST[$VARIABLE];
      } elseif ($METHOD == 'COOKIE') {
        if (!isset($_COOKIE[$VARIABLE])) $_COOKIE[$VARIABLE] = '';
        $VALUE = $_COOKIE[$VARIABLE];
      } else {
        if (!isset($_GET[$VARIABLE])) $_GET[$VARIABLE] = '';
        $VALUE = $_GET[$VARIABLE];
      }
  //-------------------------------
  // If necessary strip the slashes.
  // the "GPC" means - GET, POST
  // COOKIE.
      if (ini_get ('magic_quotes_gpc') == true) {
        $VALUE = stripslashes($VALUE);
      }
  //-------------------------------
  // Now for the different types
  // of VALIDATION's
      if (($VALIDATION & 8) == 8) {
        $VALUE = (int)$VALUE;
      }
      if (($VALIDATION & 4) == 4) {
        $VALUE = strtolower($VALUE);
      }
      if (($VALIDATION & 2) == 2) {
        $VALUE = strip_tags($VALUE);
      }
      if (($VALIDATION & 1) == 1) {
        $VALUE = trim($VALUE);
      }
  //-------------------------------
  // Finally return the value
      return $VALUE;
 }
 echo RETURN_SUBMITTED_VALUE ('ID', 'GET', 8) . '<br />';
  // Convert to an Integer
 echo RETURN_SUBMITTED_VALUE ('NAME', 'GET', 3) . '<br />';
  // Trim Whitespace and Strip HTML tags
 echo RETURN_SUBMITTED_VALUE ('GENDER', 'GET', 6) . '<br />';
  // Strip HTML tags and convert to lower case
 //-----------------------------------------------
 // If this script was loaded under the URL
 // index.php?ID=19a&NAME=Krang&GENDER=MalE
 // it would print
 //
 // 19
 // Krang
 // male
 //-----------------------------------------------
?>
For those that don’t understand binary, the numbers you see are not random, they double each time (1, 2, 4, 8, 16, 32, 64, 128, 256, 512, 1024...) which allows you to mix and match the different function, eg...
1 + 2 = 3 (Trim Whitespace + Strip HTML)
2 + 4 = 6 (Strip HTML + Convert to lower case)


zlel

Here're my 32-bit carry-discarding operations for those of you porting encryption algorithms from C.
Be warned that some of these are not very efficient compared to the native operations, especially when called by heavy-duty encryption algorithms - but not discarding the carry bit may not land you the same results you get in C, simply because PHP's bitwise operations were not designed to work on fixed-sized registers.
(If your ported encryption algo still doen't give you the same results, remember to check your Endian-ness!)
function _BF_SHR32 ($x, $bits)
{
   if ($bits==0) return $x;
   if ($bits==32) return 0;
   $y = ($x & 0x7FFFFFFF) >> $bits;
   if (0x80000000 & $x) {
       $y |= (1<<(31-$bits));    
   }
   return $y;
}
function _BF_SHL32 ($x, $bits)
{
   if ($bits==0) return $x;
   if ($bits==32) return 0;
   $mask = (1<<(32-$bits)) - 1;
   return (($x & $mask) << $bits) & 0xFFFFFFFF;
}
function _BF_GETBYTE ($x, $y)
{
   return _BF_SHR32 ($x, 8 * $y) & 0xFF;
}
function _BF_OR32 ($x, $y)
{
   return ($x | $y) & 0xFFFFFFFF;
}
function _BF_ADD32 ($x, $y)
{
   $x = $x & 0xFFFFFFFF;
   $y = $y & 0xFFFFFFFF;
   $total = 0;
   $carry = 0;
   for ($i=0; $i<4; $i++) {
       $byte_x = _BF_GETBYTE($x, $i);
       $byte_y = _BF_GETBYTE($y, $i);
       $sum = $byte_x + $byte_y;
       $result = $sum & 0xFF;
       $carryforward = _BF_SHR32($sum, 8);
       $sum = $result + $carry;
       $result = $sum & 0xFF;
       $carry = $carryforward + _BF_SHR32($sum, 8);
       $total = _BF_OR32(_BF_SHL32($result, $i*8), $total);
   }
   return $total;
}


andrew

Here is a useful function for setting flags (or bits). It takes three paramaters:
1. $var  This is the variable whose flag you want to set
2. $flag  This is the flag(s) you want set
3. $set  This is either ON or OFF
Simply adding or subtracting a flag is not a good idea. For example, if the variable is in binary 0101 (thats 5 in dec)  and you want to turn the 1 bit off subtracttion would work. 5-1=4 which would be 0100. However, the variable is 0100, and you want subtracted, 4-1 =3 or 0011. What you intended to do was to turn off the one bit regardless of whether it is on or off.
This function will turn on or off a bit(or bits) regardless of the bit's current state.
<?php
define('ON', 1);
define('OFF', 0);
function setflag(&$var, $flag, $set=ON ) {
if (($set == ON)) $var = ($var | $flag);
if (($set == OFF)) $var = ($var & ~$flag);
return;
}
?>
For a full test of this try this code:
<pre>
<?php
define ('f1', 1);
define ('f2', 2);
define ('f4', 4);
define ('f8', 8);
define('ON', 1);
define('OFF', 0);
function setflag(&$var, $flag, $set=ON ) {
if (($set == ON)) $var = ($var | $flag);
if (($set == OFF)) $var = ($var & ~$flag);
return;
}
function dbi($var){ // display number as binary (four bits)
$output = ($var & f8) ? '1' : '0';
$output .= ($var & f4) ? '1' : '0';
$output .= ($var & f2) ? '1' : '0';
$output .= ($var & f1) ? '1' : '0';
return $output;
}
$var1 = ( f8 | f2 | f1 );
echo ("    " . dbi($var1). "\n" );
echo ("ON  " . dbi(f4). "\n" );
setflag($var1, f4, ON);
echo ("IS  " . dbi($var1). "\n" );
echo ("\n");
$var2 = ( f8 | f2 | f1 );
echo ("    " . dbi($var2). "\n" );
echo ("OFF " . dbi(f1). "\n" );
setflag($var2, f1, OFF);
echo ("IS  " . dbi($var2). "\n" );
echo ("\n");
echo ("\n");
$var3 = ( f8 | f2 | f1 );
echo ("    " . dbi($var3). "\n" );
echo ("ON  " . dbi((f4 | f1)). "\n" );
setflag($var3, (f4 | f1), ON);
echo ("IS  " . dbi($var3). "\n" );
echo ("\n");
$var4 = ( f8 | f2 | f1 );
echo ("    " . dbi($var4). "\n" );
echo ("OFF " . dbi((f4 | f1)). "\n" );
setflag($var4, (f4 | f1), OFF);
echo ("IS  " . dbi($var4). "\n" );
echo ("\n");
?>
</pre>
Which returns:
   1011
ON  0100
IS  1111
   1011
OFF 0001
IS  1010
   1011
ON  0101
IS  1111
   0100
OFF 0101
IS  0000


gcg

function xnor($a, $b) {
return ~($a ^ $b);
}
XNOR is very usefull ;D


nina cording

For those who were searching for a way to actually rotate the bits of a number, here are some little functions I wrote:
<?php
function bitRotate32($value,$amount) {
if ($amount>0) {
$amount %= 32;
$value = ($value<<$amount) | ($value>>(32-$amount));
} elseif ($amount<0) {
$amount = -$amount%32;
$value = ($value>>$amount) | ($value<<(32-$amount));
}
return $value;
}
function bitRotate($value,$amount,$bits) {
$mask = ($bits<32) ? 0x7fffffff >> (31-$bits) : 0xffffffff;
if ($amount>0) {
$amount %= $bits;
$value = ($value<<$amount) | ($value>>($bits-$amount));
} elseif ($amount<0) {
$amount = -$amount%$bits;
$value = ($value>>$amount) | ($value<<($bits-$amount));
}
return $value & $mask;
}
// test the rotation:
$test = 4123;
for ($i=0; $i<64; $i++) {
$value = bitRotate($test,-$i,8); // rotates 8 bits to the left (-$amount)
echo sprintf("%032b<br/>",$value);
}
?>


richard-slater.co.uk

For those (like me) who are trying to do bit masking with very large numbers, here is a useful function to do the work for you.
<?php
 function isBitSet($bitMask, $bitMap)
 {
   return (bool) gmp_intval(gmp_div(gmp_and($bitMask, $bitMap),$bitMask));
 }
?>


achim

For all of you who are new to bitwise operatons (like me)...
There is a great article on gamedev.net explaining the basics of this:
"Bitwise Operations in C" by Joseph "Ironblayde" Farrell
http://www.gamedev.net/reference/articles/article1563.asp


gemini_5

Extending the comment by andrew at thepenry dot net:
His (slightly altered) function for reference:
<?php
function setflag(&$var, $flag, $set) {
  if (($set == 1)) $var = ($var | $flag);
  if (($set == 0)) $var = ($var & ~$flag);
  return;
}
?>
You could shorten the operations to:
<?php
$var |= $flag;  // for setting
$var &= ~$flag; // for unsetting
?>
Which kind of eliminates the need for a function.


don dot hosek

Don't forget operator precedence. == has a higher precedence than does & so in the cases that you've written
if (9 & 8 == 8) echo 'true'; else echo 'false';
is the same as 9 & (8 ==8) which is 9 & true or 9 & 1 which is 1 which is true
if (8 & 8 == 8) echo 'true'; else echo 'false';
is the same as 8 & (8 == 8) which is 8 & true or 8 & 1 which is 0 which is false
Putting in parentheses is required to cause the bitwise and to take place before the comparison.


john l

Bitwise operators are swell, but (a & b & c & d) == a
is not a way to test for four-way equality. If a is zero, it'll always be true, and in general it will be true any time a has no bits not also in the other three values.


tanstep

Beware that strings can be ANDed, XORed, and ORed just fine. When printing the results of a bitwise operation, results can be a bit confusing, since operands may be converted to strings BEFORE bitwise operator execution.
so, use this:
   print('result: ');
   print(pow(2, $pos) & $this->_bits);
   print('
');
NOT this
   print("result: " . pow(2, $pos) & $this->_bits . "
");


séb.

Another practical case...
<?php
   header('Content-Type: text/plain') ;
   // We want to know the power-2 based numbers of $x
   $x = 9124 ;
   $n = 1 ;
   while ( $x > 0 ) {
       if ( $x & 1 == 1 ) {
           echo $n, "\n" ;
       }
       $n *= 2 ;
       $x >>= 1 ;
   }
   
   // Will output...
   // 4
   // 32
   // 128
   // 256
   // 512
   // 8192
?>


temp dot 2004-03-27

Always use type casting!
<?php
echo (134 & 512) . "\n";
echo ("134" & "512") . "\n";
echo  ((int)"134" & (int)"512") . "\n";
?>
Output:
0
110    (wrong!)
0


joel

All shifts are signed shifts. The shift is performed with the shift count modulo 32, which explains the behavior which looks like a bit rotation, mentioned above.
Example:
$bit = 0x20000000;
print "$bit << 5 == " . ($bit << 5) . $prod . "<br />";
print "$bit >> 5 == " . ($bit >> 5) . $prod . "<br />";
print "$bit >> 37 == " . ($bit >> 37) . $prod . "<br />";
$bit = 4;
print "$bit >> 5 == " . ($bit >> 5) . $prod . "<br />";
print "$bit << 5 == " . ($bit << 5) . $prod . "<br />";
print "$bit << 37 == " . ($bit << 37) . $prod . "<br />";
Results:
536870912 << 5 == 0
536870912 >> 5 == 16777216
536870912 >> 37 == 16777216
4 >> 5 == 0
4 << 5 == 128
4 << 37 == 128


lars dot jensen

A useful set of functions, making it easier to play with bits as a set of booleans. $bit is a integer between 1 and 32 representing the position of the bit you wish to manipulate.
<?php
function setbit($val, $bit) {
if (readbit($val, $bit)) return $val;
return $val += '0x'.dechex(1<<($bit-1));
}

function clearbit($val, $bit) {
if (!readbit($val, $bit)) return $val;
return $val^(0+('0x'.dechex(1<<($bit-1))));
}
function readbit($val, $bit) {
return ($val&(0+('0x'.dechex(1<<($bit-1)))))?'1':'0';
}

function debug($var, $bitlength=32) {
for ($j=$bitlength;$j>0;$j--) {
echo readbit($var, $j);
if ($j%4 == 1) echo ' ';
}
}
?>


séb.

A bitwise operators practical case :
<?php
// We want to know the red, green and blue values of this color :
$color = 0xFEA946 ;
$red = $color >> 16 ;
$green = ($color & 0x00FF00) >> 8 ;
$blue = $color & 0x0000FF ;
printf('Red : %X (%d), Green : %X (%d), Blue : %X (%d)',
$red, $red, $green, $green, $blue, $blue) ;
// Will display...
// Red : FE (254), Green : A9 (169), Blue : 46 (70)
?>


rdewaard

@jbrand1 at uwe_emm_bee_see dot edu:
"I have to be careful when I add roles so that it's 2^whatever.  I wish I knew how to change the auto_increment so that it was just a bit shift."
If you store your roles in MySQL you might consider NOT using a table 'roles' but adding a field 'roles' to the table 'user' using the datatype SET for that field. The name for each role will have a decimal value 2^whatever! See http://www.vbmysql.com/articles/mysqlsetdatatype.html for details and ideas.


keuleu

<?php
function xor_swap(&$a, &$b) {
  if($a==$b) {
      return;
  }
  $c = $a ^ $b;
  $b = $c ^ $b;
  $a = $c ^ $a;
}
?>
Explanation:
$c=$a*^$b*;
$b=$c^$b*; => $b=($a*^$b*)^$b*; => $b=$a*^0; => $b=$a*;
$a=$c^$a*; => $a=($a*^$b*)^$a; => $a=$b*^0; =>$a=$b*;
*original value of the variable
Now a version of xor_swap() with no buffer ($c):
<?php
function xor_swap(&$a,&$b){
  if($a==$b) {
      return;
  }
  $a=$a^$b;
  $b=$a^$b;
  $a=$a^$b;
}
?>
Explanation:
$a=$a*^$b*;
$b=$a^$b*; => $b=($a*^$b*)^$b*; => $b=$a*;
$a=$a^$b; => $a=($a*^$b*)^$a*; =>$a=$b*;
* original value of the variable


~

<?php
function xor_swap(&$a, &$b) {
if($a==$b) {
return;
}
$c = $a ^ $b;  
$b = $c ^ $b;
$a = $c ^ $a;
}
function swap (&$a, &$b) {
$buffer = $a;
$a = $b;
$b = $buffer;
}
$a = 1; $b = 2;
echo '$a is '.$a.'<br />$b is '.$b.'<hr />';
swap($a, $b);
echo '$a is '.$a.'<br />$b is '.$b.'<hr />';
xor_swap($a, $b);
echo '$a is '.$a.'<br />$b is '.$b;
?>
Output:
$a is 1
$b is 2
--------------
$a is 2
$b is 1
--------------
$a is 1
$b is 2


xavier daull

<?php
// Extract part of a binary data - due to windows system limitations (and this code), bit extracted length($firstbit to $lastbit included) is limited to 31 bits
function sub_bindata($mybindata, $firstbit = 7, $lastbit = 0, $highestbitfirst = true)
{
// 1. Create a bit mask of the right size by triming left and right
// 2. select bits by an AND on $mybindata
// 3. shift right to get only length needed
if($highestbitfirst) return (((0x7FFFFFFF >> (30+$lastbit-$firstbit))<<($lastbit)) & $mybindata) >> ($lastbit);
else return (((0x7FFFFFFF >> (30-$lastbit+$firstbit))<<(30-$lastbit)) & $mybindata) >> (30-$lastbit);
}
?>


Change Language


Follow Navioo On Twitter
Operator Precedence
Arithmetic Operators
Assignment Operators
Bitwise Operators
Comparison Operators
Error Control Operators
Execution Operators
Incrementing/Decrementing Operators
Logical Operators
String Operators
Array Operators
Type Operators
eXTReMe Tracker