Top > Bitwise Operator

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
    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.
  • 読みこなすのが難しいところです。 (..; コンピューターと友達になるためには、これを知る必要がありそうだし、トリッキーなことができそうなんだが -- toto 2007-03-30 (金) 02:04:59

コメントを書き込むためには、Hatena で認証をお願いします。

add a note User Contributed Notes

Bitwise Operators

gcG
02-Mar-2007 09:23
function xnor($a, $b) {

   return ~($a ^ $b);

}
XNOR is very usefull ;D
bryanagee at gmail dot com
09-Feb-2007 04:19
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;
       }

?>
zewt at hotmail dot com
12-Jan-2007 04:28
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.
rizal dot almashoor at gmail dot com
14-Nov-2006 09:12
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);

}
?>
nicolaas francken
30-Oct-2006 08:28
The function below can show you which bits are on. In this way, you can store eight Boolean values in a single number (from 0 to 255):

echo '<br />the number you provided is '.$_GET["j"].'.';
for($i = 1; $i < 9; $i++) {

echo '<br /> &nbsp; bit '.$i.' is '.bitcheck($i, $_GET["j"]); 

}

function bitcheck($a, $b) {

if((pow(2,($a-1))) & ($b)) {
 return "ON";
}
else {
 return "OFF";
}

}
keuleu at hotmail dot com
20-Sep-2006 07:10

?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



28-Aug-2006 07:49

?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
27-Apr-2006 04: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
?>
Xavier Daull
05-Feb-2006 06:34

?php

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);

}

?>
John L
03-Feb-2006 07:11
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.
Nina Cording
30-Oct-2005 01:50
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 = 4123;
for ($i=0; $i<64; $i++) {

   $value = bitRotate($test,-$i,8); // rotates 8 bits to the left (-$amount)
   echo sprintf("%032b<br/>",$value);

}

?>
zlel grxnslxves13 at hotmail dot com~=s/x/ee/g
27-Oct-2005 11:30
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 "<br>This is the value we want";
echo "<br>3851262585";

echo "<br>The result of a native xor operation on integer values is treated as a signed integer";
echo "<br>".($x ^ $y);

echo "<br>We therefore perform the MSB separately";
echo "<br>".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
zlel
27-Oct-2005 09:22
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;

}
Tbrendstrup
29-Sep-2005 09:23
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<br>%1\$032b<br>%2\$032b<br>%1\$0d<br>%2\$0d<br>",$val, $val >> 1 );

printf("logic shift on a negative integer<br>%1\$032b<br>%2\$032b<br>%1\$0d<br>%2\$0d<br>",$val, lshiftright($val, 1));

printf("logic shift on a positive integer<br>%1\$032b<br>%2\$032b<br>%1\$0d<br>%2\$0d<br>",-$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
junk at spheresys dot com
22-Sep-2005 03:25
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).
Planev ea2005#planev.com
02-Sep-2005 10:42
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;

}
Eric Swanson
01-Sep-2005 09:19
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));

}

$result = 3851235679 ^ 43814; //= -443704711

$result = binxor(3851235679, 43814); //= 3851262585

$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 />");
alexrussell101 at gmail dot com
25-Jul-2005 08:28
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.
redduck666 at gmail dot com
23-Jul-2005 07:26
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 ;)
S颮
19-Apr-2005 11: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颮
05-Mar-2005 08: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 04: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
21-Jan-2005 07: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 05:06
The function below can be rewritten to this:

?php

function setflag (&$var, $flag, $set = true)
{

  $var = $set ? ($var | $flag) : ($var & ~$flag);

}

?>
Gemini_5
08-Sep-2004 07: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
15-Apr-2004 04: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 10: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
29-Mar-2004 04: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
26-Mar-2004 08: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
27-Feb-2004 07: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*1. "\n" );
setflag($var3, (f4 | f1), ON);
echo ("IS " . dbi($var3). "\n" );
echo ("\n");
$var4 = ( f8 | f2 | f1 );
echo (" " . dbi($var4). "\n" );
echo ("OFF " . dbi*2. "\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
26-Feb-2004 04: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 06: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
18-Feb-2004 02: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
18-Feb-2004 02: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
05-Jan-2004 03: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:

  1. ----------+--------+
    UsernameRoleID
  2. ----------+--------+
    admin1
    suser2
    user4
  3. ----------+--------+

My roles table looks like this:

  1. -------------------------------+--------+
    RoleNameRoleID
  2. -------------------------------+--------+
    System Administrator1
    Super User2
    User4
  3. -------------------------------+--------+

My menus table looks like this:

  1. -------------------+---------------------+---------+
    Menu_TitleMenuFileRoles
  2. -------------------+---------------------+---------+
    DataData.php7
    All DataAll_Data.php3
    ShutdownShutdown.php1
  3. -------------------+---------------------+---------+

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 04: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
05-Dec-2003 07: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
28-Oct-2003 07: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 05: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

add a note

Comparison Operators Assignment Operators


Last updated: Mon, 26 Mar 2007

  

show source | credits | sitemap | contact | advertising | mirror sites
Copyright © 2001-2007 The PHP Group
All rights reserved. This mirror generously provided by: PacketBusiness, Inc.
Last updated: Fri Mar 30 01:34:46 2007 JST


*1 f4 | f1
*2 f4 | f1

リロード     ホーム 一覧 検索 最終更新 バックアップ リンク元   ヘルプ   最終更新のRSS
Last-modified: Sat, 04 Dec 2010 22:48:46 JST (2563d)