search for in the  
<Assignment OperatorsComparison Operators>
Last updated: Thu, 19 May 2005

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

Table 15-3. Bitwise Operators

ExampleNameResult
$a & $bAndBits that are set in both $a and $b are set.
$a | $bOrBits that are set in either $a or $b are set.
$a ^ $bXor Bits that are set in $a or $b but not both are set.
~ $aNot Bits that are set in $a are not set, and vice versa.
$a << $bShift left Shift the bits of $a $b steps to the left (each step means "multiply by two")
$a >> $bShift 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.



User Contributed Notes
Bitwise Operators
Séb.
19-Apr-2005 09:28
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
?>
Séb.
04-Mar-2005 05:13
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)
?>
icy at digitalitcc dot com
24-Feb-2005 01:24
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) {
}
louis /at/ mulliemedia.com
20-Jan-2005 04:12
Note that the ^ operator, unlike in some other languages, is *not* the same as the pow() function.
dasch at ulmail dot net
14-Dec-2004 02:06
The function below can be rewritten to this:

<?php

function setflag (&$var, $flag, $set = true)
{
  
$var = $set ? ($var | $flag) : ($var & ~$flag);
}

?>
Gemini_5
07-Sep-2004 05:06
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.
rdewaard at DONTSPAMME dot xs4all dot nl
14-Apr-2004 02:36
@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.
xert
31-Mar-2004 07:11
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
temp dot 2004-03-27 at fobit dot de
28-Mar-2004 01:58
Always use type casting!

<?php
echo (134 & 512) . "\n";
echo (
"134" & "512") . "\n";
echo  ((int)
"134" & (int)"512") . "\n";
?>

Output:

0
110    (wrong!)
0
lars dot jensen at ljweb dot com
25-Mar-2004 05:27
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 ' ';
       }
   }
?>
andrew at thepenry dot net
26-Feb-2004 04:11
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
crizza at sdf dot lonestar dot org
25-Feb-2004 01:27
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.
richard-slater.co.uk
22-Feb-2004 03:07
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));
  }
?>
tanstep at hotmail dot com
17-Feb-2004 11:14
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)
tanstep at hotmail dot com
17-Feb-2004 11:03
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('<br>');

NOT this
   print("result: " . pow(2, $pos) & $this->_bits . "<br>");
jbrand1 at uwe_emm_bee_see dot edu
04-Jan-2004 12:04
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.
achim at gmeiner dot cc
27-Dec-2003 01:21
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
krang at krang dot org dot uk
04-Dec-2003 04:30
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)
rob at thijssen dot co dot uk
27-Oct-2003 04:14
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";
}
joel at alpsgiken dot gr dot jp
10-Oct-2001 03:58
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

<Assignment OperatorsComparison Operators>
 Last updated: Thu, 19 May 2005
Copyright © 2001-2005 The PHP Group
All rights reserved.
This unofficial mirror is operated at: The Server Pages
Last updated: Thu May 19 17:35:34 2005 CDT