Руководство and php

Bitwise operators allow evaluation and manipulation of specific
bits within an integer.

Bitwise Operators

Example Name Result
$a & $b And Bits that are set in both $a and $b are set.
$a | $b Or (inclusive or) Bits that are set in either $a or $b are set.
$a ^ $b Xor (exclusive or) 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»)

Bit shifting in PHP is arithmetic.
Bits shifted off either end are discarded.
Left shifts have zeros shifted in on the right while the sign
bit is shifted out on the left, meaning the sign of an operand
is not preserved.
Right shifts have copies of the sign bit shifted in on the left,
meaning the sign of an operand is preserved.

Use parentheses to ensure the desired
precedence.
For example, $a & $b == true evaluates
the equivalency then the bitwise and; while
($a & $b) == true evaluates the bitwise and
then the equivalency.

If both operands for the &, | and
^ operators are strings, then the operation will be
performed on the ASCII values of the characters that make up the strings and
the result will be a string. In all other cases, both operands will be
converted to integers
and the result will be an integer.

If the operand for the ~ operator is a string, the
operation will be performed on the ASCII values of the characters that make
up the string and the result will be a string, otherwise the operand and the
result will be treated as integers.

Both operands and the result for the << and
>> operators are always treated as integers.

PHP's error_reporting ini setting uses bitwise values,
providing a real-world demonstration of turning
bits off. To show all errors, except for notices,
the php.ini file instructions say to use:
E_ALL & ~E_NOTICE
      
This works by starting with E_ALL:
00000000000000000111011111111111
Then taking the value of E_NOTICE...
00000000000000000000000000001000
... and inverting it via ~:
11111111111111111111111111110111
Finally, it uses AND (&) to find the bits turned
on in both values:
00000000000000000111011111110111
      
Another way to accomplish that is using XOR (^)
to find bits that are on in only one value or the other:
E_ALL ^ E_NOTICE
      

error_reporting can also be used to demonstrate turning bits on.
The way to show just errors and recoverable errors is:
E_ERROR | E_RECOVERABLE_ERROR
      
This process combines E_ERROR
00000000000000000000000000000001
and
00000000000000000001000000000000
using the OR (|) operator
to get the bits turned on in either value:
00000000000000000001000000000001
      

Example #1 Bitwise AND, OR and XOR operations on integers


<?php
/*
* Ignore the top section,
* it is just formatting to make output clearer.
*/
$format = '(%1$2d = %1$04b) = (%2$2d = %2$04b)'
. ' %3$s (%4$2d = %4$04b)' . "n";

echo <<<EOH

--------- --------- -- ---------
result value op test
--------- --------- -- ---------
EOH;/*
* Here are the examples.
*/
$values = array(0, 1, 2, 4, 8);
$test = 1 + 4;

echo

"n Bitwise AND n";
foreach (
$values as $value) {
$result = $value & $test;
printf($format, $result, $value, '&', $test);
}

echo

"n Bitwise Inclusive OR n";
foreach (
$values as $value) {
$result = $value | $test;
printf($format, $result, $value, '|', $test);
}

echo

"n Bitwise Exclusive OR (XOR) n";
foreach (
$values as $value) {
$result = $value ^ $test;
printf($format, $result, $value, '^', $test);
}
?>

The above example will output:

 ---------     ---------  -- ---------
 result        value      op test
 ---------     ---------  -- ---------
 Bitwise AND
( 0 = 0000) = ( 0 = 0000) & ( 5 = 0101)
( 1 = 0001) = ( 1 = 0001) & ( 5 = 0101)
( 0 = 0000) = ( 2 = 0010) & ( 5 = 0101)
( 4 = 0100) = ( 4 = 0100) & ( 5 = 0101)
( 0 = 0000) = ( 8 = 1000) & ( 5 = 0101)

 Bitwise Inclusive OR
( 5 = 0101) = ( 0 = 0000) | ( 5 = 0101)
( 5 = 0101) = ( 1 = 0001) | ( 5 = 0101)
( 7 = 0111) = ( 2 = 0010) | ( 5 = 0101)
( 5 = 0101) = ( 4 = 0100) | ( 5 = 0101)
(13 = 1101) = ( 8 = 1000) | ( 5 = 0101)

 Bitwise Exclusive OR (XOR)
( 5 = 0101) = ( 0 = 0000) ^ ( 5 = 0101)
( 4 = 0100) = ( 1 = 0001) ^ ( 5 = 0101)
( 7 = 0111) = ( 2 = 0010) ^ ( 5 = 0101)
( 1 = 0001) = ( 4 = 0100) ^ ( 5 = 0101)
(13 = 1101) = ( 8 = 1000) ^ ( 5 = 0101)

Example #2 Bitwise XOR operations on strings


<?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
echo 2 ^ "3"; // Outputs 1
// 2 ^ ((int)"3") == 1
echo "2" ^ 3; // Outputs 1
// ((int)"2") ^ 3 == 1
?>

Example #3 Bit shifting on integers


<?php
/*
* Here are the examples.
*/
echo "n--- BIT SHIFT RIGHT ON POSITIVE INTEGERS ---n";$val = 4;
$places = 1;
$res = $val >> $places;
p($res, $val, '>>', $places, 'copy of sign bit shifted into left side');$val = 4;
$places = 2;
$res = $val >> $places;
p($res, $val, '>>', $places);$val = 4;
$places = 3;
$res = $val >> $places;
p($res, $val, '>>', $places, 'bits shift out right side');$val = 4;
$places = 4;
$res = $val >> $places;
p($res, $val, '>>', $places, 'same result as above; can not shift beyond 0');

echo

"n--- BIT SHIFT RIGHT ON NEGATIVE INTEGERS ---n";$val = -4;
$places = 1;
$res = $val >> $places;
p($res, $val, '>>', $places, 'copy of sign bit shifted into left side');$val = -4;
$places = 2;
$res = $val >> $places;
p($res, $val, '>>', $places, 'bits shift out right side');$val = -4;
$places = 3;
$res = $val >> $places;
p($res, $val, '>>', $places, 'same result as above; can not shift beyond -1');

echo

"n--- BIT SHIFT LEFT ON POSITIVE INTEGERS ---n";$val = 4;
$places = 1;
$res = $val << $places;
p($res, $val, '<<', $places, 'zeros fill in right side');$val = 4;
$places = (PHP_INT_SIZE * 8) - 4;
$res = $val << $places;
p($res, $val, '<<', $places);$val = 4;
$places = (PHP_INT_SIZE * 8) - 3;
$res = $val << $places;
p($res, $val, '<<', $places, 'sign bits get shifted out');$val = 4;
$places = (PHP_INT_SIZE * 8) - 2;
$res = $val << $places;
p($res, $val, '<<', $places, 'bits shift out left side');

echo

"n--- BIT SHIFT LEFT ON NEGATIVE INTEGERS ---n";$val = -4;
$places = 1;
$res = $val << $places;
p($res, $val, '<<', $places, 'zeros fill in right side');$val = -4;
$places = (PHP_INT_SIZE * 8) - 3;
$res = $val << $places;
p($res, $val, '<<', $places);$val = -4;
$places = (PHP_INT_SIZE * 8) - 2;
$res = $val << $places;
p($res, $val, '<<', $places, 'bits shift out left side, including sign bit');/*
* Ignore this bottom section,
* it is just formatting to make output clearer.
*/
function p($res, $val, $op, $places, $note = '') {
$format = '%0' . (PHP_INT_SIZE * 8) . "bn";printf("Expression: %d = %d %s %dn", $res, $val, $op, $places);

echo

" Decimal:n";
printf(" val=%dn", $val);
printf(" res=%dn", $res);

echo

" Binary:n";
printf(' val=' . $format, $val);
printf(' res=' . $format, $res);

if (

$note) {
echo
" NOTE: $noten";
}

echo

"n";
}
?>

Output of the above example on 32 bit machines:

--- BIT SHIFT RIGHT ON POSITIVE INTEGERS ---
Expression: 2 = 4 >> 1
 Decimal:
  val=4
  res=2
 Binary:
  val=00000000000000000000000000000100
  res=00000000000000000000000000000010
 NOTE: copy of sign bit shifted into left side

Expression: 1 = 4 >> 2
 Decimal:
  val=4
  res=1
 Binary:
  val=00000000000000000000000000000100
  res=00000000000000000000000000000001

Expression: 0 = 4 >> 3
 Decimal:
  val=4
  res=0
 Binary:
  val=00000000000000000000000000000100
  res=00000000000000000000000000000000
 NOTE: bits shift out right side

Expression: 0 = 4 >> 4
 Decimal:
  val=4
  res=0
 Binary:
  val=00000000000000000000000000000100
  res=00000000000000000000000000000000
 NOTE: same result as above; can not shift beyond 0


--- BIT SHIFT RIGHT ON NEGATIVE INTEGERS ---
Expression: -2 = -4 >> 1
 Decimal:
  val=-4
  res=-2
 Binary:
  val=11111111111111111111111111111100
  res=11111111111111111111111111111110
 NOTE: copy of sign bit shifted into left side

Expression: -1 = -4 >> 2
 Decimal:
  val=-4
  res=-1
 Binary:
  val=11111111111111111111111111111100
  res=11111111111111111111111111111111
 NOTE: bits shift out right side

Expression: -1 = -4 >> 3
 Decimal:
  val=-4
  res=-1
 Binary:
  val=11111111111111111111111111111100
  res=11111111111111111111111111111111
 NOTE: same result as above; can not shift beyond -1


--- BIT SHIFT LEFT ON POSITIVE INTEGERS ---
Expression: 8 = 4 << 1
 Decimal:
  val=4
  res=8
 Binary:
  val=00000000000000000000000000000100
  res=00000000000000000000000000001000
 NOTE: zeros fill in right side

Expression: 1073741824 = 4 << 28
 Decimal:
  val=4
  res=1073741824
 Binary:
  val=00000000000000000000000000000100
  res=01000000000000000000000000000000

Expression: -2147483648 = 4 << 29
 Decimal:
  val=4
  res=-2147483648
 Binary:
  val=00000000000000000000000000000100
  res=10000000000000000000000000000000
 NOTE: sign bits get shifted out

Expression: 0 = 4 << 30
 Decimal:
  val=4
  res=0
 Binary:
  val=00000000000000000000000000000100
  res=00000000000000000000000000000000
 NOTE: bits shift out left side


--- BIT SHIFT LEFT ON NEGATIVE INTEGERS ---
Expression: -8 = -4 << 1
 Decimal:
  val=-4
  res=-8
 Binary:
  val=11111111111111111111111111111100
  res=11111111111111111111111111111000
 NOTE: zeros fill in right side

Expression: -2147483648 = -4 << 29
 Decimal:
  val=-4
  res=-2147483648
 Binary:
  val=11111111111111111111111111111100
  res=10000000000000000000000000000000

Expression: 0 = -4 << 30
 Decimal:
  val=-4
  res=0
 Binary:
  val=11111111111111111111111111111100
  res=00000000000000000000000000000000
 NOTE: bits shift out left side, including sign bit

Output of the above example on 64 bit machines:

--- BIT SHIFT RIGHT ON POSITIVE INTEGERS ---
Expression: 2 = 4 >> 1
 Decimal:
  val=4
  res=2
 Binary:
  val=0000000000000000000000000000000000000000000000000000000000000100
  res=0000000000000000000000000000000000000000000000000000000000000010
 NOTE: copy of sign bit shifted into left side

Expression: 1 = 4 >> 2
 Decimal:
  val=4
  res=1
 Binary:
  val=0000000000000000000000000000000000000000000000000000000000000100
  res=0000000000000000000000000000000000000000000000000000000000000001

Expression: 0 = 4 >> 3
 Decimal:
  val=4
  res=0
 Binary:
  val=0000000000000000000000000000000000000000000000000000000000000100
  res=0000000000000000000000000000000000000000000000000000000000000000
 NOTE: bits shift out right side

Expression: 0 = 4 >> 4
 Decimal:
  val=4
  res=0
 Binary:
  val=0000000000000000000000000000000000000000000000000000000000000100
  res=0000000000000000000000000000000000000000000000000000000000000000
 NOTE: same result as above; can not shift beyond 0


--- BIT SHIFT RIGHT ON NEGATIVE INTEGERS ---
Expression: -2 = -4 >> 1
 Decimal:
  val=-4
  res=-2
 Binary:
  val=1111111111111111111111111111111111111111111111111111111111111100
  res=1111111111111111111111111111111111111111111111111111111111111110
 NOTE: copy of sign bit shifted into left side

Expression: -1 = -4 >> 2
 Decimal:
  val=-4
  res=-1
 Binary:
  val=1111111111111111111111111111111111111111111111111111111111111100
  res=1111111111111111111111111111111111111111111111111111111111111111
 NOTE: bits shift out right side

Expression: -1 = -4 >> 3
 Decimal:
  val=-4
  res=-1
 Binary:
  val=1111111111111111111111111111111111111111111111111111111111111100
  res=1111111111111111111111111111111111111111111111111111111111111111
 NOTE: same result as above; can not shift beyond -1


--- BIT SHIFT LEFT ON POSITIVE INTEGERS ---
Expression: 8 = 4 << 1
 Decimal:
  val=4
  res=8
 Binary:
  val=0000000000000000000000000000000000000000000000000000000000000100
  res=0000000000000000000000000000000000000000000000000000000000001000
 NOTE: zeros fill in right side

Expression: 4611686018427387904 = 4 << 60
 Decimal:
  val=4
  res=4611686018427387904
 Binary:
  val=0000000000000000000000000000000000000000000000000000000000000100
  res=0100000000000000000000000000000000000000000000000000000000000000

Expression: -9223372036854775808 = 4 << 61
 Decimal:
  val=4
  res=-9223372036854775808
 Binary:
  val=0000000000000000000000000000000000000000000000000000000000000100
  res=1000000000000000000000000000000000000000000000000000000000000000
 NOTE: sign bits get shifted out

Expression: 0 = 4 << 62
 Decimal:
  val=4
  res=0
 Binary:
  val=0000000000000000000000000000000000000000000000000000000000000100
  res=0000000000000000000000000000000000000000000000000000000000000000
 NOTE: bits shift out left side


--- BIT SHIFT LEFT ON NEGATIVE INTEGERS ---
Expression: -8 = -4 << 1
 Decimal:
  val=-4
  res=-8
 Binary:
  val=1111111111111111111111111111111111111111111111111111111111111100
  res=1111111111111111111111111111111111111111111111111111111111111000
 NOTE: zeros fill in right side

Expression: -9223372036854775808 = -4 << 61
 Decimal:
  val=-4
  res=-9223372036854775808
 Binary:
  val=1111111111111111111111111111111111111111111111111111111111111100
  res=1000000000000000000000000000000000000000000000000000000000000000

Expression: 0 = -4 << 62
 Decimal:
  val=-4
  res=0
 Binary:
  val=1111111111111111111111111111111111111111111111111111111111111100
  res=0000000000000000000000000000000000000000000000000000000000000000
 NOTE: bits shift out left side, including sign bit

Warning

Use functions from the gmp extension for
bitwise manipulation on numbers beyond PHP_INT_MAX.

wbcarts at juno dot com

11 years ago


BITWISE FLAGS for Custom PHP Objects

Sometimes I need a custom PHP Object that holds several boolean TRUE or FALSE values. I could easily include a variable for each of them, but as always, code has a way to get unweildy pretty fast. A more intelligent approach always seems to be the answer, even if it seems to be overkill at first.

I start with an abstract base class which will hold a single integer variable called $flags. This simple integer can hold 32 TRUE or FALSE boolean values. Another thing to consider is to just set certain BIT values without disturbing any of the other BITS -- so included in the class definition is the setFlag($flag, $value) function, which will set only the chosen bit. Here's the abstract base class definition:

<?php# BitwiseFlag.phpabstract class BitwiseFlag
{
  protected
$flags;/*
   * Note: these functions are protected to prevent outside code
   * from falsely setting BITS. See how the extending class 'User'
   * handles this.
   *
   */
 
protected function isFlagSet($flag)
  {
    return ((
$this->flags & $flag) == $flag);
  }

  protected function

setFlag($flag, $value)
  {
    if(
$value)
    {
     
$this->flags |= $flag;
    }
    else
    {
     
$this->flags &= ~$flag;
    }
  }
}
?>

The class above is abstract and cannot be instantiated, so an extension is required. Below is a simple extension called User -- which is severely truncated for clarity. Notice I am defining const variables AND methods to use them.

<?php# User.phprequire('BitwiseFlag.php');

class

User extends BitwiseFlag
{
  const
FLAG_REGISTERED = 1; // BIT #1 of $flags has the value 1
 
const FLAG_ACTIVE = 2;     // BIT #2 of $flags has the value 2
 
const FLAG_MEMBER = 4;     // BIT #3 of $flags has the value 4
 
const FLAG_ADMIN = 8;      // BIT #4 of $flags has the value 8public function isRegistered(){
    return
$this->isFlagSet(self::FLAG_REGISTERED);
  }

  public function

isActive(){
    return
$this->isFlagSet(self::FLAG_ACTIVE);
  }

  public function

isMember(){
    return
$this->isFlagSet(self::FLAG_MEMBER);
  }

  public function

isAdmin(){
    return
$this->isFlagSet(self::FLAG_ADMIN);
  }

  public function

setRegistered($value){
   
$this->setFlag(self::FLAG_REGISTERED, $value);
  }

  public function

setActive($value){
   
$this->setFlag(self::FLAG_ACTIVE, $value);
  }

  public function

setMember($value){
   
$this->setFlag(self::FLAG_MEMBER, $value);
  }

  public function

setAdmin($value){
   
$this->setFlag(self::FLAG_ADMIN, $value);
  }

  public function

__toString(){
    return
'User [' .
      (
$this->isRegistered() ? 'REGISTERED' : '') .
      (
$this->isActive() ? ' ACTIVE' : '') .
      (
$this->isMember() ? ' MEMBER' : '') .
      (
$this->isAdmin() ? ' ADMIN' : '') .
   
']';
  }
}
?>

This seems like a lot of work, but we have addressed many issues, for example, using and maintaining the code is easy, and the getting and setting of flag values make sense. With the User class, you can now see how easy and intuitive bitwise flag operations become.

<?phprequire('User.php')$user = new User();
$user->setRegistered(true);
$user->setActive(true);
$user->setMember(true);
$user->setAdmin(true);

echo

$user// outputs: User [REGISTERED ACTIVE MEMBER ADMIN]?>


grayda dot NOSPAM at DONTSPAM dot solidinc dot org

13 years ago


Initially, I found bitmasking to be a confusing concept and found no use for it. So I've whipped up this code snippet in case anyone else is confused:

<?php// The various details a vehicle can have
   
$hasFourWheels = 1;
   
$hasTwoWheels  = 2;
   
$hasDoors      = 4;
   
$hasRedColour  = 8;$bike          = $hasTwoWheels;
   
$golfBuggy     = $hasFourWheels;
   
$ford          = $hasFourWheels | $hasDoors;
   
$ferrari       = $hasFourWheels | $hasDoors | $hasRedColour;$isBike        = $hasFourWheels & $bike; # False, because $bike doens't have four wheels
   
$isGolfBuggy   = $hasFourWheels & $golfBuggy; # True, because $golfBuggy has four wheels
   
$isFord        = $hasFourWheels & $ford; # True, because $ford $hasFourWheels?>

And you can apply this to a lot of things, for example, security:

<?php// Security permissions:
   
$writePost = 1;
   
$readPost = 2;
   
$deletePost = 4;
   
$addUser = 8;
   
$deleteUser = 16;// User groups:
   
$administrator = $writePost | $readPosts | $deletePosts | $addUser | $deleteUser;
   
$moderator = $readPost | $deletePost | $deleteUser;
   
$writer = $writePost | $readPost;
   
$guest = $readPost;// function to check for permission
   
function checkPermission($user, $permission) {
        if(
$user & $permission) {
            return
true;
        } else {
            return
false;
        }
    }
// Now we apply all of this!
   
if(checkPermission($administrator, $deleteUser)) {
       
deleteUser("Some User"); # This is executed because $administrator can $deleteUser
   
}?>

Once you get your head around it, it's VERY useful! Just remember to raise each value by the power of two to avoid problems


frankemeks77 at yahoo dot com

10 years ago


Just learning Bitwise Shift Operators.

The easiest way to resolve a bitwise  shift operators is my multiply or dividing each step by two for left shift or right shift respectively

Example:

LEFT SHIFT

<?php echo 8 << 3; //64 ?>



//same as

<?php echo 8 * 2 * 2 * 2; ?>



RIGHT SHIFT

<?php echo 8 >> 3; //1 ?>



//same as

<?php echo ((8/2)/2)/2; //1 ?>



//Solving on a paper 8/2 = 4/2 = 2/2 = 1


ASchmidt at Anamera dot net

3 years ago


Setting, unsetting and testing single and multiple bits in a bitmask:

<?php
   
const    FLAG_A    =    0b0001,
           
FLAG_B    =    0b0010,
           
FLAG_C    =    0b0100,
           
FLAG_D    =    0b1000;

                const   

COMBO_BC = FLAG_B | FLAG_C;$bitmask = 0b000;// Setting individual flags.
   
$bitmask |=    FLAG_B;        // Sets FLAG_B (=2)
   
$bitmask |=    FLAG_C;        // also sets FLAG_C (=4)

        // Testing single or multiple flags.

echo (bool)( $bitmask & FLAG_B );                            // True, B is set.echo (bool)( $bitmask & (FLAG_A | FLAG_B) );                // True, A or B is set.echo (bool)( $bitmask & FLAG_B and $bitmask & FLAG_C );        // True, B and C are set.
   
echo (bool)( ( $bitmask & (FLAG_B | FLAG_C) ) ^ (FLAG_B | FLAG_C) );    // False if B and C are set.
   
echo (bool)( ( $bitmask & COMBO_BC ) ^ COMBO_BC );            // False if B and C are set.echo (bool)( $bitmask & FLAG_C and $bitmask & FLAG_D );        // False, C and D are NOT BOTH set.
   
echo (bool)( ( $bitmask & (FLAG_C | FLAG_D) ) ^ (FLAG_C | FLAG_D) );    // True, if C and D are NOT BOTH set.

        // Resetting single flag.

$bitmask &= $bitmask ^ FLAG_B;    // Unsets B
   
$bitmask &= $bitmask ^ FLAG_A;    // A remains unset.
   
var_dump( $bitmask );            // Only C still set (=4)

        // Resetting multiple flags.

$bitmask &= $bitmask ^ ( FLAG_C | FLAG_D );    // Unsets C and/or D
   
var_dump( $bitmask );            // No flags set (=0)


m0sh at hotmail dot com

14 years ago


@greenone - nice function, thanks. I've adapted it for key usage:

<?php
function bitxor($str, $key) {
   
$xorWidth = PHP_INT_SIZE*8;
   
// split
   
$o1 = str_split($str, $xorWidth);
   
$o2 = str_split(str_pad('', strlen($str), $key), $xorWidth);
   
$res = '';
   
$runs = count($o1);
    for(
$i=0;$i<$runs;$i++)
       
$res .= decbin(bindec($o1[$i]) ^ bindec($o2[$i]));      
    return
$res;
}
?>


zooly at globmi dot com

13 years ago


Here is an example for bitwise leftrotate and rightrotate.

Note that this function works only with decimal numbers - other types can be converted with pack().

<?phpfunction rotate ( $decimal, $bits) {$binary = decbin($decimal);

  return (

bindec(substr($binary, $bits).substr($binary, 0, $bits))
  );

}

// Rotate 124 (1111100) to the left with 1 bitsecho rotate(124, 1);// = 121 (1111001)

// Rotate 124 (1111100) to the right with 3 bits

echo rotate(124, -3);// = 79 (1001111)?>


S?b.

18 years ago


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


zewt at hotmail dot com

16 years ago


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.


zlel grxnslxves13 at hotmail dot com~=s/x/ee/g

17 years ago


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

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


vivekanand dot pathak25 at gmail dot com

10 years ago


$a =     9;
$b =     10;
echo $a & $b;

place value   128  64  32  16   8  4   2   1
$a                     0      0    0     0    1  0   0   1   =9
$b                     0      0    0     0    1   0  1   0   =10

result   8 

only bit they share together is the 8 bit. So 8 gets returned.

  $a =     36;
$b =     103;
echo $a & $b;

place value   128  64  32  16   8    4   2   1
$a                     0      0    1     0    0    1   0   0   =36
$b                     0      1    1     0    0    1   1   1   =103

result  32+4 = 36
the only bits these two share together are the bits 32 and 4 which when added together return 36.

$a =     9;
$b =     10;
echo $a | $b;

place value   128  64  32  16   8  4   2   1
$a                     0      0    0     0    1  0   0   1   =9
$b                     0      0    0     0    1   0  1   0   =10

result 8+2+1 = 11
3 bits set, in the 8, 2, and 1 column.add those up 8+2+1 and you get 11

$a =     9;
$b =     10;
echo $a ^ $b;

place value   128  64  32  16   8  4   2   1
$a                     0      0    0     0    1  0   0   1   =9
$b                     0      0    0     0    1   0  1   0   =10

result  2+1 = 3
the 2 bit and the 1 bit that they each have set but don't share. Soooo 2+1 = 3


Silver

14 years ago


Regarding what Bob said about flags, I'd like to point out there's a 100% safe way of defining flags, which is using hexadecimal notation for integers:

<?php
define
("f0", 0x1); // 2^0
define("f1", 0x2); // 2^1
define("f2", 0x4); // 2^2
define("f3", 0x8); // 2^3
define("f4", 0x10); // 2^4
define("f5", 0x20); // 2^5
// ...
define("f20", 0x1000000); // 2^20
define("f21", 0x2000000); // 2^21
define("f22", 0x4000000); // 2^22
define("f23", 0x8000000); // 2^23
define("f24", 0x10000000); // 2^24
// ... up to 2^31
?>

I always avoid using decimal notation when I have a large amount of different flags, because it's very easy to misspell numbers like 2^20 (1048576).


amckenzie4 at gmail dot com

12 years ago


If, like me, you've never thought about how PHP deals with binary, the output of the bitwise NOT may confuse you.  For instance, this:

$bin = 2;
$notbin = ~$bin;

echo "Bin: " . decbin($bin) . "  !bin:  " . decbin($notbin) . "n";

returns this:

Bin: 10  !bin:  1111111111111111111111111111111111111111111111111111111111111101

The reason is that all binary numbers are treated as 32 bits, even if you've manually entered less.  In order to get the result I expected (01), it was necessary to AND the result with the number of bits I wanted:  in this case, 2 (the number 3, in decimal).  Be aware that all return values will have zeros removed from the left until they reach a bit that is set to 1.  Continuing the above example, the following:

$notbin_2 = ~$bin & '3';
echo "!bin & 3:  " . decbin($notbin_2) . "n";

returns this:

!bin & 3:  1

Note that the actual value was a string of 31 zeros followed by a 1, but the zeros were not shown.  This is probably a good thing.

Furthermore, the NOT operator uses two's complement, which means the number you get may be even stranger than you expect:  using two's complement means that ~2 == -3.  There are plenty of good explanations of two's complement online, so I won't go into that question here.

If what you want is just to reverse a string of bits without any interpretation, you can use a function like this:

function bitnot($bin)
{
   $not = "";
   for ($i = 0; $i < strlen($bin); $i++)
   {
      if($bin[$i] == 0) { $not .= '1'; }
      if($bin[$i] == 1) { $not .= '0'; }
   }
   return $not;
}

It takes a binary string of any length, reverses the bits, and returns the new string.  You can then treat it as a binary number, use bindec() to turn it into a decimal, or whatever you want.

I hope this helps someone as much as it would have helped me a week ago!


icy at digitalitcc dot com

18 years ago


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) {
}


forlamp at msn dot com

15 years ago


two's complement logical operation for 32-bit.

$x must be (int) when passing it to this function to work properly.

function comp2($x)      // 32bit bitwise complement
{
    $mask = 0x80000000;

    if ($x < 0)
    {
        $x &= 0x7FFFFFFF;
        $x = ~$x;

        return $x ^ $mask;
    }
    else
    {
        $x = $x ^ 0x7FFFFFFF;

        return $x | $mask;
    }
}


ivoras at gmail dot com

11 years ago


As an additional curiosity, for some reason the result of the operation ("18" & "32") is "10". In other words, try avoiding using the binary operators on strings :)

spencer-p-moy at example dot com

11 years ago


The NOT or complement operator ( ~ ) and negative binary numbers can be confusing.

~2 = -3  because you use the formula  ~x = -x - 1  The bitwise complement of a decimal number is the negation of the number minus 1.

NOTE: just using 4 bits here for the examples below but in reality PHP uses 32 bits.

Converting a negative decimal number (ie: -3) into binary takes 3 steps:
1) convert the positive version of the decimal number into binary (ie: 3 = 0011)
2) flips the bits (ie: 0011 becomes 1100)
3) add 1 (ie: 1100  + 0001 = 1101)

You might be wondering how does 1101 = -3. Well PHP uses the method "2's complement" to render negative binary numbers. If the left most bit is a 1 then the binary number is negative and you flip the bits and add 1. If it is 0 then it is positive and you don't have to do anything. So 0010 would be a positive 2. If it is 1101, it is negative and you flip the bits to get 0010. Add 1 and you get 0011 which equals -3.


josh at joshstrike dot com

12 years ago


More referencing this for myself than anything... if you need to iterate through every possible binary combination where $n number of flags are set to 1 in a mask of $bits length:

<?php

echo masksOf(3,10);

function

masksOf($n,$bits) {

   
$u = pow(2,$bits)-1; //start value, full flags on.

   
$masks = array();

    while (
$u>0) {

       
$z = numflags($u);

        if (
$z==$n) array_push($masks,$u);

       
$u--;

    }

    return (
$masks);   

}

function

numflags($n) {

   
$k = 0;

    while (
$n) {

       
$k += $n & 1;

       
$n = $n >> 1;

    }

    return (
$k);
//    alternately:

//    $u = 0;

//    for ($k=1;$k<=$n;$k*=2) {

//        $u+=($n&$k?1:0);

//    }

//    return ($u);

}

?>


cw3theophilus at gmail dot com

14 years ago


For those who are looking for a circular bit shift function in PHP (especially useful for cryptographic functions) that works with negtive values, here is a little function I wrote:

(Note: It took me almost a whole day to get this to work with negative $num values (I couldn't figure out why it sometimes worked and other times didn't), because PHP only has an arithmatic and not a logical bitwise right shift like I am used to. I.e. 0x80000001>>16 will ouputs (in binary) "1111 1111 1111 1111 1000 0000 0000 0000" instead of "0000 0000 0000 0000 1000 0000 0000 0000" like you would expect. To fix this you have to apply the mask (by bitwise &) equal to 0x7FFFFFFF right shifted one less than the offset you are shifting by.)

<?php
function circular_shift($num,$offset) { //Do a nondestructive circular bitwise shift, if offset positive shift left, if negative shift right
   
$num=(int)$num;
   
$mask=0x7fffffff; //Mask to cater for the fact that PHP only does arithmatic right shifts and not logical i.e. PHP doesn't give expected output when right shifting negative values
   
if ($offset>0) {
       
$num=($num<<$offset%32) | (($num>>(32-$offset%32)) & ($mask>>(31-$offset%32)));
    }
    elseif (
$offset<0){
       
$offset=abs($offset);
       
$num=(($num>>$offset%32) & ($mask>>(-1+$offset%32))) | ($num<<(32-$offset%32));
    }
    return
$num;
}
?>


aba at example dot com

11 years ago


It is true that if both the left-hand and right-hand parameters are strings, the bitwise operator will operate on the characters' ASCII values. However, a complement is necessary to complete this sentence.
It is not irrelevant to point out that the decimal character's ASCII value have different binary values.

<?php
if (('18' & '32') == '10') {
    echo
ord('18'); //return decimal value 49, which have binary value 110001
   
echo ord('32'); //return decimal value 51, which have binary value 110011
   
echo ord('10'); //return decimal value 49, which have binary value 110001
    //Therefore 110001 & 110011 = 110001
}
?>


Tbrendstrup

17 years ago


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.

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


erich at seachawaii dot com

10 years ago


Just a note regarding negative shift values, as the documentation states each shift is an integer multiply or divide (left or right respectively) by 2.  That means a negative shift value (the right hand operand) effects the sign of the shift and NOT the direction of the shift as I would have expected. 
FE. 0xff >> -2 results in 0x0
and 0xff << -2 result in 0xFFFFFFFFC0000000 (dependant on PHP_INT_MAX)

sag at ich dot net

9 years ago


me reimplement for bitwise NOT (~)

    protected function flipBin($number) {
        $bin = str_pad(base_convert($number, 10, 2), 32, 0, STR_PAD_LEFT);
        for ($i = 0; $i < 32; $i++) {
            switch ($bin{$i}) {
                case '0' :
                    $bin{$i} = '1';
                    break;
                case '1' :
                    $bin{$i} = '0';
                    break;
            }
        }
        return bindec($bin);
    }

the benefit is, it works with numbers greater MAX_INT


Anonymous

13 years ago


Beware that PHP's << and >> operators, unlike the other bitwise operators do not work on ASCII values; << and >> cast their operands to integer (when possible) before shifting and will always return an integer result.

For example:

<?php
$foo
= "1"; // chr(49)
var_dump($foo << 1); // Output is int(2)$foo = "!"; // chr(33)
var_dump($foo << 1); // Output is int(0)
?>


Bob

14 years ago


Here is an easy way to use bitwise operation for 'flag' functionality.
By this I mean managing a set of options which can either be ON or OFF, where zero or more of these options may be set and each option may only be set once. (If you are familiar with MySQL, think 'set' datatype).
Note: to older programmers, this will be obvious.

Here is the code:
<?php
function set_bitflag(/*variable-length args*/)
{
   
$val = 0;
    foreach(
func_get_args() as $flag) $val = $val | $flag;
    return
$val;
}
function
is_bitflag_set($val, $flag)
{
    return ((
$val & $flag) === $flag);
}
// Define your flags
define('MYFLAGONE', 1); // 0001
define('MYFLAGTWO', 2); // 0010
define('MYFLAGTHREE', 4); // 0100
define('MYFLAGFOUR', 8); // 1000
?>

I should point out: your flags are stored in a single integer. You can store loads of flags in a single integer.

To use my functions, say you wanted to set MYFLAGONE and MYFLAGTHREE, you would use:
<?php
$myflags
= set_bitflags(MYFLAGONE, MYFLAGTHREE);
?>
Note: you can pass set_bitflags() as many flags to set as you want.

When you want to test later if a certain flag is set, use e.g.:
<?php
if(is_bitflag_set($myflags, MYFLAGTWO))
{
    echo
"MYFLAGTWO is set!";
}
?>

The only tricky part is defining your flags. Here is the process:
1.  Write a list of your flags
2.  Count them
3.  Define the last flag in your list as 1 times 2 to the power of <count> minus one. ( I.E. 1*2^(<count>-1) )
3. Working backwards through your list, from the last to the first, define each one as half of the previous one. You should reach 1 when you get to the first

If you want to understand binary numbers, bits and bitwise operation better, the wikipedia page explains it well - http://en.wikipedia.org/wiki/Bitwise_operation.


Eric Swanson

17 years ago


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


Adam

13 years ago


Be careful of order of operations.

for example, you may want to check if the second bit is set:

<?php
if ($x & 2 == 2) {
   
/* code */
}
?>

is different than

<?php
if (($x & 2) == 2) {
   
/* code */
}
?>

and the latter of the two should be used.


Core Xii

12 years ago


Be very careful when XOR-ing strings! If one of the values is empty (0, '', null) the result will also be empty!

<?php
var_dump
(1234 ^ 0); // int(1234)
var_dump(1234 ^ ''); // int(1234)
var_dump(1234 ^ null); // int(1234)
var_dump('hello world' ^ 0); // int(0)
var_dump('hello world' ^ ''); // string(0) ""
var_dump('hello world' ^ null); // int(0)
?>

This seems rather inconsistent behavior. An integer XOR'd with zero results the original integer. But a string XOR'd with an empty value results an empty value!

My password hashing function was always returning the same hash... Because I was XOR-ing it with a salt that was sometimes empty!


Anonymous

11 years ago


To make very clear why ("18" & "32") is "10".
1) they they are both strings ,
2) "&" operator works on strings by taking each !Character! from each string and make a bit wise & between them and add this value to the resulting string

So:
"18" is made up of two characters: 0x31, 0x38
"32" is made up of two characters: 0x33, 0x32
----RESULT-----
0x31 & 0x33 = 0x31 => "1"
0x38 & 0x32 = 0x30 => "0"

and the result is "10" which is 100% correct.


razvan_bc at yahoo dot com

2 months ago


if you want to set a bit in php you don't need a new extension (avoid using of extensions could be slow down your php!) then with minimum effort you can have:

<?phpfunction setbit($v,$b=0){
        return (
1<<$b)|$v;//($v&$x);
}

    echo

sprintf('%b', setbit(0b00000010,0));/*

bits position:          76543210
target number:  0b00000010
bit 0-------------------------^

so

bits position:          76543210
result:                      00000011
(sprintf will show  "11" value)
*/

?>

same results with anonymous functions from a constant! ..
<?php

define

('setbits',fn($v,$b=0)=>(1<<$b)|$v);
echo
sprintf('%b',(setbits)(0b00000010,0));?>

all test i made are on last PHP Version => 8.2.4RC1 !


biziclop at vipmail dot hu

3 years ago


A fast algorithm (Brian Kernighan's) to count all bits set to 1 in an integer, modified to work with signed ints.
It does the same as https://php.net/gmp_popcount except for ordinary integers.

<?php
function count_set_bits( $n ){
  if(
$n >= 0 ){  for( $count = 0$n;       ++$count $n &= $n - 1;  }
           else{  for(
$count = 1$n << 1;  ++$count $n &= $n - 1;  }
  return
$count;
}

echo

'This PHP uses ' . count_set_bits(-1) .'-bit integers.';
?>


joey

7 years ago


If you want a quick one liner for reversing binary and performance/sanity isn't an issue:

    function reverse_bits($n) {
        return (int)base_convert(strrev(str_pad(base_convert($n, 10, 2), PHP_INT_SIZE * 8, 0, STR_PAD_LEFT)), 2, 10);
    }

Expect it to behave strangely for the signed bit. Best to use for < PHP_INT_SIZE * 8 to avoid peculiarity. You can also skip the cast if you don't mind keeping your number as a string. base convert appears to work for large precision or perhaps arbitrary but be prepared for strangeness (double, mixed types, precision loss, etc) if you need to work on the revolting number.

Use at your own peril.


bartbons at debster.nl

15 years ago


@kendsnyder at gmail dot com

Thanx for your great function. But your function is not 100% correct. It should be:

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) - 1 <$i || ($binComparison{$i}==="1" && $binNumber{$i}==="0") ) {
                return false;  
            }
        }
        return true;
    }
}

Mind the 'minus 1' on "if( strlen($binNumber) - 1 <$i".

cheers, Bart


Nina Cording

17 years ago


For those who were searching for a way to actually rotate the bits of a number, here are some little functions I wrote:

<?phpfunction 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);
}
?>


luis at rosety dot com

7 years ago


Example of function using bitwise operations for converting hexadecimal color (usually given as 6 hexadecimal digit string, into separated RGB integers)

<?phpfunction hex2rgb($hex){$dec = hexdec($hexcolor);               // $hex string to decimal value
   
$r = $dec & hexdec('FF0000');          //Mask for red
   
$g = $dec & hexdec('00FF00');         //Mask for green
   
$b = $dec & hexdec('0000FF');         //Mask for bluereturn array($r>>16, $g>>8, $b);       // Shift full right each color from its original position
}
?>

Example of use

<?php
$rgb
= hex2rgb('112233');
echo
"red: ".$rgb[0]."n";
echo
"green: ".$rgb[1]."n";
echo
"blue: ".$rgb[2]."n";
?>

Would produce:

red: 17       
green: 34
blue: 51

Since:
dechex(17) = '#11'
dechex(34) = '#22'
dechex(51) = '#33'


J. Ketting

8 years ago


@zooly

Don't forget the leading zeros.
It's very important if you want to write a function similar to the assembly instructions 'ror' and 'rol' (Rotate on Right and Rotate on Left), because of dword value; rotating the binary always takes 32 positions and includes the leading zeros!
So this is the right way:

<?phpfunction rotate ($decimal, $bits) {$binary = decbin($decimal);
 
$binary = str_pad($binary, 32, '0', STR_PAD_LEFT);
  return (
   
bindec(substr($binary, $bits).substr($binary, 0, $bits))
  );

}

?>

Look at this assembly code:

mov edx, 1bf5616c
ror edx, 8

After this operation: edx = 0x6c1bf561 (binary: 1101100000110111111010101100001)
But your code returns 0x0d9bf561 (binary: 1101100110111111010101100001)
In order to get the right value you have to add the leading zeros by adding that line with strpad() (see above). Very important!


Logical Operators

Example Name Result
$a and $b And true if both $a and $b are true.
$a or $b Or true if either $a or $b is true.
$a xor $b Xor true if either $a or $b is true, but not both.
! $a Not true if $a is not true.
$a && $b And true if both $a and $b are true.
$a || $b Or true if either $a or $b is true.

The reason for the two different variations of «and» and «or»
operators is that they operate at different precedences. (See
Operator
Precedence.)

Example #1 Logical operators illustrated


<?php// --------------------
// foo() will never get called as those operators are short-circuit
$a = (false && foo());
$b = (true || foo());
$c = (false and foo());
$d = (true or foo());// --------------------
// "||" has a greater precedence than "or"

// The result of the expression (false || true) is assigned to $e
// Acts like: ($e = (false || true))

$e = false || true;// The constant false is assigned to $f before the "or" operation occurs
// Acts like: (($f = false) or true)
$f = false or true;var_dump($e, $f);// --------------------
// "&&" has a greater precedence than "and"

// The result of the expression (true && false) is assigned to $g
// Acts like: ($g = (true && false))

$g = true && false;// The constant true is assigned to $h before the "and" operation occurs
// Acts like: (($h = true) and false)
$h = true and false;var_dump($g, $h);
?>

The above example will output
something similar to:

bool(true)
bool(false)
bool(false)
bool(true)

Lawrence

15 years ago


Note that PHP's boolean operators *always* return a boolean value... as opposed to other languages that return the value of the last evaluated expression.

For example:

$a = 0 || 'avacado';
print "A: $an";

will print:

A: 1

in PHP -- as opposed to printing "A: avacado" as it would in a language like Perl or JavaScript.

This means you can't use the '||' operator to set a default value:

$a = $fruit || 'apple';

instead, you have to use the '?:' operator:

$a = ($fruit ? $fruit : 'apple');


dumitru at floringabriel dot com

6 years ago


In addition to what Lawrence said about assigning a default value, one can now use the Null Coalescing Operator (PHP 7). Hence when we want to assign a default value we can write:

$a = ($fruit ?? 'apple');
//assigns the $fruit variable content to $a if the $fruit variable exists or has a value that is not NULL, or assigns the value 'apple' to $a if the $fruit variable doesn't exists or it contains the NULL value


thisleenobleNOSPAMPLEASE at mac dot com

6 years ago


In order to kind of emulate the way javascript assigns the first non-false value in an expression such as this:

var v = a || b || c || d;

I wrote a little helper method that I put in a function dump library (here presented as a bare function):

<?php
function either($a, $b){
       
$val = $a ? $a : $b;
       
/*
             Yes, I know the fixed parameters in the function
             are redundant since I could just use func_get_args,
             but in most instances I'll be using this a replacement
             for the ternary operator and only passing two values.
             I don't want to invoke the additional process below
             unless I REALLY have to.
        */
       
$args = func_get_args();
        if(
$val === false && count($args) > 2){
           
$args = array_slice($args, 2);

            foreach(

$args as $arg){
                if(
$arg !== false){
                   
$val = $arg;
                    break;
                }
            }
        }
        return
$val;
    }
?>

Now instead of:

$v = $a ? $a : $b;

I write:

$v = either($a, $b);

but more importantly, instead of writing:

$v = $a ? $a : ($b ? $b : $c);

I write:

$v = either($a, $b, $c);

or indeed:

$v = either($a, $b, $c, $d, $e, $f, $g, $h);


egst

2 years ago


In response to Lawrence about || always returning a boolean:

Instead of

$x ? $x : 'fallback'

you can also use the "elvis operator":

$x ?: 'fallback'

which is useful in cases, where the left-hand side of the ternary operator is too long type, is too complex to calculate twice, or has side-effects.

It also combines nicely with the ?? operator, which is equivalent to an empty() check (both isset() and `!= false`):

$x->y ?? null ?: 'fallback';

instead of:

empty($x->y) ? $x->y : 'fallback'


pepesantillan at gmail dot com

15 years ago


worth reading for people learning about php and programming: (adding extras <?php ?> to get highlighted code)

about the following example in this page manual:
Example#1 Logical operators illustrated

...
<?php
// "||" has a greater precedence than "or"
$e = false || true; // $e will be assigned to (false || true) which is true
$f = false or true; // $f will be assigned to false
var_dump($e, $f);// "&&" has a greater precedence than "and"
$g = true && false; // $g will be assigned to (true && false) which is false
$h = true and false; // $h will be assigned to true
var_dump($g, $h);
?>
_______________________________________________end of my quote...

If necessary, I wanted to give further explanation on this and say that when we write:
$f = false or true; // $f will be assigned to false
the explanation:

"||" has a greater precedence than "or"

its true. But a more acurate one would be

"||" has greater precedence than "or" and than "=", whereas "or" doesnt have greater precedence than "=", so

<?php
$f
= false or true;//is like writting($f = false ) or true;//and$e = false || true;is the same as$e = (false || true);?>

same goes for "&&" and "AND".

If you find it hard to remember operators precedence you can always use parenthesys - "(" and ")". And even if you get to learn it remember that being a good programmer is not showing you can do code with fewer words. The point of being a good programmer is writting code that is easy to understand (comment your code when necessary!), easy to maintain and with high efficiency, among other things.


momrom at freenet dot de

14 years ago


Evaluation of logical expressions is stopped as soon as the result is known.
If you don't want this, you can replace the and-operator by min() and the or-operator by max().

<?php
function a($x) { echo 'Expression '; return $x; }
function
b($x) { echo 'is '; return $x; }
function
c($x) { echo $x ? 'true.' : 'false.' ;}c( a( false ) and b( true ) ); // Output: Expression false.
c( min( a( false ), b( true ) ) ); // Output: Expression is false.c( a( true ) or b( true ) ); // Output: Expression true.
c( max( a( true ), b( true ) ) ); // Output: Expression is true.
?>

This way, values aren't automaticaly converted to boolean like it would be done when using and or or. Therefore, if you aren't sure the values are already boolean, you have to convert them 'by hand':

<?php
c
( min( (bool) a( false ), (bool) b( true ) ) );
?>


phpnet at zc dot webhop dot net

10 years ago


This works similar to javascripts short-curcuit assignments and setting defaults. (e.g.  var a = getParm() || 'a default';)

<?php($a = $_GET['var']) || ($a = 'a default');?>

$a gets assigned $_GET['var'] if there's anything in it or it will fallback to 'a default'
Parentheses are required, otherwise you'll end up with $a being a boolean.


Andrew

15 years ago


> <?php
> your_function() or return "whatever";
>
?>

doesn't work because return is not an expression, it's a statement. if return was a function it'd work fine. :/

brian at zickzickzick dot com

9 years ago


This has been mentioned before, but just in case you missed it:

<?php
   
// Defaults --

    //If you're trying to gat 'Jack' from:

$jack = false or 'Jack'; // Try:
   
$jack = false or $jack = 'Jack';//The other option is:
   
$jack = false ? false : 'Jack';
?>


peter dot kutak at NOSPAM dot gmail dot com

15 years ago


$test = true and false;     ---> $test === true

$test = (true and false);  ---> $test === false

$test = true && false;      ---> $test === false

NOTE: this is due to the first line actually being

($test = true) and false;

due to "&&" having a higher precedence than "=" while "and" has a lower one


anatoliy at ukhvanovy dot name

8 years ago


If you want to use the '||' operator to set a default value, like this:

<?php
$a
= $fruit || 'apple'; //if $fruit evaluates to FALSE, then $a will be set to TRUE (because (bool)'apple' == TRUE)
?>

instead, you have to use the '?:' operator:

<?php
$a
= ($fruit ? $fruit : 'apple');//if $fruit evaluates to FALSE, then $a will be set to 'apple'
?>

But $fruit will be evaluated twice, which is not desirable. For example fruit() will be called twice:
<?php
function fruit($confirm) {
    if(
$confirm)
        return
'banana';
}
$a = (fruit(1) ? fruit(1) : 'apple');//fruit() will be called twice!
?>

But since «since PHP 5.3, it is possible to leave out the middle part of the ternary operator» (http://www.php.net/manual/en/language.operators.comparison.php#language.operators.comparison.ternary), now you can code like this:

<?php
$a
= ($fruit ? : 'apple'); //this will evaluate $fruit only once, and if it evaluates to FALSE, then $a will be set to 'apple'
?>

But remember that a non-empty string '0' evaluates to FALSE!

<?php
$fruit
= '1';
$a = ($fruit ? : 'apple'); //this line will set $a to '1'
$fruit = '0';
$a = ($fruit ? : 'apple'); //this line will set $a to 'apple', not '0'!
?>


void at informance dot info

9 years ago


To assign default value in variable assignation, the simpliest solution to me is:

<?php
$v
= my_function() or $v = "default";
?>

It works because, first, $v is assigned the return value from my_function(), then this value is evaluated as a part of a logical operation:
* if the left side is false, null, 0, or an empty string, the right side must be evaluated and, again, because 'or' has low precedence, $v is assigned the string "default"
* if the left side is none of the previously mentioned values, the logical operation ends and $v keeps the return value from my_function()

This is almost the same as the solution from [phpnet at zc dot webhop dot net], except that his solution (parenthesis and double pipe) doesn't take advantage of the "or" low precedence.

NOTE: "" (the empty string) is evaluated as a FALSE logical operand, so make sure that the empty string is not an acceptable value from my_function(). If you need to consider the empty string as an acceptable return value, you must go the classical "if" way.


martinholtcbi at gmail dot com

5 months ago


In PHP, the || operator only ever returns a boolean. For a chainable assignment operator, use the ?: "Elvis" operator.

JavaScript:
let a = false;
let b = false;
let c = true;
let d = false;
let e = a || b || c || d;
// e === c

<?PHP
$a
= false;
$b = false;
$c = true;
$d = false;
$e = $a ?: $b ?: $c ?: $d;
// $e === $c
?>

Credit to @egst and others for the insight. This is merely a rewording for (formerly) lost JavaScript devs like myself.


samantha at adrichem dot nu

8 years ago


<?php
    $res
|= true;
   
var_dump($res);
?>

does not/no longer returns a boolean (php 5.6) instead it returns int 0 or 1

Manucyan

4 years ago


So...
A || B   may be different from  B || A

for exemple :

unset($a);
if (    ($a < 0)   ||   (!isset($a))   )
echo 'Hello!';  

//      return error:  "Notice: Undefined variable: a "

unset($a);
if (    (!isset($a))   ||    ($a < 0)  )
echo 'Hello!';  

//      return   'Hello!'

practical example with an age check over 17 years:
if (    (!isset($age))   ||    ($age < 17)  )
$error_age = true;

this example will not display a php error if the age is not entered


vasko at tsintsev dot com

6 years ago


Here is something useful for OR ( or any other ) bitwise comparison:

$a = 0;
$b = 1;

printf('$a = %1$04b | $b = %2$04b ...  PROCESSED is: %3$s ( %3$04b )', $a, $b, ($a | $b));


drevilkuko at gmail dot com

7 years ago


using NULL coalesce operator:

<?php
$nc
= true == false ?? 'no';
var_dump($nc); // false$nc = null ?? 'yes';
var_dump($nc); // yes$username = null == false ?? 'no';
var_dump($nc); // true$nc = $_GET['something'] ?? 'default';
var_dump($nc); // default$nc = !isset($_GET['something']) ?? 'wtf';
var_dump($nc); // true$nc = isset($_GET['something']) ?? 'wtf';
var_dump($nc); // false$_POST['second'] = 'chain';
$nc = $_GET['first'] ?? $_POST['second'] ?? $_REQUEST['third'] ?? 'wtf';
var_dump($nc); // chain
?>


mcodingset at outlook dot com

4 years ago


// __forFun ...
// Example Logical `or` operator

$a = true;                  // true|false or something for test :)
$b = "I'm a string result"; // use|test `string` or `object`

if (!$a or !$c = $b) {
    $c = 'Hey';
}

// print result
var_dump($c); // "I'm a string result"

Have Fun!


moschris at gmail dot com

6 years ago


Unlike C++ and related languages, side effects in the left operand may NOT be used in the right operand.

e.g. if ($a=1 && $a>0)
will produce an unassigned error if $a has not previously been assigned a value.


4077

8 years ago


Assign a value to a variable if it isn't defined

<?php
isset($x) || $x = 123;

print

$x; // 123
?>



instead of:

<?php
if ( !isset($x)) {

   
$x = 123;

}
// or
$x = isset($x) ? $x : 123;
// or
$x = isset($x) ?: 123;

?>



editor's note: In PHP 7 you could use the coalesce operator and do:

<?php

$x
= $x ?? 123;


paranoiq at centrum dot cz

15 years ago


and, or and xor can be used as conditional constructs:

<?php
// do_that() is executed only if do_this() returns false
if($something) do_this() or do_that();
// $b is assigned to $b, do_that() is executed if $b is false
if($something) $a = $b or do_that();// do_that() is executed only if do_this() returns true
if($something) do_this() and do_that();
// $b is assigned to $b, do_that() is executed if $b is true
if($something) $a = $b and do_that();// both do_that() and do_this() are executed..
if($something) do_this() xor do_that();
// .. so the behaviour is same as:
if($something) {
   
do_this();
   
do_that();
}
?>

for understanding what happens if $b is NULL or do_this() returns NULL, read the avbentem's comment on NULL type. generaly speaking, NULL is threated like false in most cases.


Логические операторы

Пример Название Результат
$a and $b И TRUE если и $a, и $b TRUE.
$a or $b Или TRUE если или $a, или $b TRUE.
$a xor $b Исключающее или TRUE если $a, или $b TRUE, но не оба.
! $a Отрицание TRUE если $a не TRUE.
$a && $b И TRUE если и $a, и $b TRUE.
$a || $b Или TRUE если или $a, или $b TRUE.

Смысл двух разных вариантов для операторов «and» и «or» в том, что
они работают с различными приоритетами (смотрите таблицу
Приоритет выполнения операторов).

Пример #1 Объяснение логических операторов


<?php// --------------------
// foo() никогда не буде вызвана, так как эти операторы являются шунтирующими (short-circuit)
$a = (false && foo());
$b = (true  || foo());
$c = (false and foo());
$d = (true  or  foo());// --------------------
// "||" имеет больший приоритет, чем "or"

// Результат выражения (false || true) присваивается переменной $e
// Действует как: ($e = (false || true))

$e false || true;// Константа false присваивается $f, а затем значение true игнорируется
// Действует как: (($f = false) or true)
$f false or true;var_dump($e$f);// --------------------
// "&&" имеет больший приоритет, чем "and"

// Результат выражения (true && false) присваивается переменной $g
// Действует как: ($g = (true && false))

$g true && false;// Константа true присваивается $h, а затем значение false игнорируется
// Действует как: (($h = true) and false)
$h true and false;var_dump($g$h);
?>

Результатом выполнения данного примера
будет что-то подобное:

bool(true)
bool(false)
bool(false)
bool(true)

Вернуться к: Операторы

Summary: in this tutorial, you’ll learn about the PHP AND operator and how to use it to build a complex logical expression.

Introduction to the PHP AND operator

The logical AND operator accepts two operands and returns true if both operands are true; otherwise, it returns false.

PHP uses the and keyword to represent the logical AND operator:

expression1 and expression2

The following table illustrates the result of the and operator:

expression1 expression2 expression1 and expression2
true true true
true false false
false true false
false false false

Since PHP keywords are case-insensitive, the AND and and operators are the same:

expression1 AND expression2

By convention, you should use the and operator in the lowercase format.

In addition to using the and keyword, PHP uses && as the logical AND operator:

expression1 && expression2

The && and and operators return the same result. The only difference between the && and and operators are their precedences.

The and operator has higher precedence than the && operator. The precedence of an operator specifies the order in which PHP evaluates.

Suppose that you want to offer discounts to customers who buy more than three items with a price of more than 99. To determine whether customers can get a discount or not, you can use the AND operator as follows:

<?php

$price = 100;
$qty = 5;

$discounted = $qty > 3 && $price > 99;


var_dump($discounted);
Code language: HTML, XML (xml)

Output:

bool(true)Code language: JavaScript (javascript)

If you change the $qty to 2, the $discounted will be false like this:

<?php

$price = 100;
$qty = 2;

$discounted = $qty > 3 && $price > 99;


var_dump($discounted);Code language: HTML, XML (xml)

In practice, you’ll use the logical AND operator in the if, if-else, if-elseif, while, and do-while statements.

Short-circuiting

When the value of the first operand is false, the logical AND operator knows that the result must be also false. In this case, it doesn’t evaluate the second operand. This process is called short-circuiting.

See the following example:

<?php

$debug = false;
$debug && print('PHP and operator demo!');
Code language: HTML, XML (xml)

How it works.

  • First, define the variable $debug and initialize it to false.
  • Second, use the logical AND operator to combine the $debug and print(). Since $debug is false, PHP doesn’t evaluate the call to the print() function.

If you change the $debug to true, you’ll see a message in the output:

<?php

$debug = true;
$debug && print('PHP and operator demo!');Code language: HTML, XML (xml)

Output:

PHP and operator demo!Code language: plaintext (plaintext)

Summary

  • Use the PHP AND operator (and, &&) to combine two boolean expressions and returns true if both expressions evaluate to true; otherwise, it returns false.
  • The logical AND operator is short-circuiting.

Did you find this tutorial useful?

  • Логическое ИЛИ (OR и ||)
  • Логическое И (AND и &&)
  • Исключающее ИЛИ (XOR)
  • Логическое НЕ (!)

PHP поддерживает стандартные логические операторы AND и &&, OR и ||, !(не) и XOR. Логические операторы позволяют сравнивать результаты работы двух операндов (значения или выражения) с целью определения факта возвращения одним из них или обоими значения true или false и выбора соответствующего продолжения выполнения сценария в зависимости от возвращенного значения. Как и операторы сравнения, логические операторы возвращают одно логическое значение — true либо false, в зависимости от значений находящихся по обе стороны от оператора.

Логические операторы

Пример Название Результат
$i and $y Логическое И TRUE, если оба операнда имеют значение TRUE.
$i or $y Логическое ИЛИ TRUE, если хотя бы один операнд имеет значение TRUE.
$i xor $y Исключающее или TRUE, если только один из операндов имеет значение TRUE, но не оба.
!$i Логическое НЕ (Отрицание) TRUE, если операнд имеет значение FALSE, и FALSE, если операнд имеет значение TRUE.
$i && $y Логическое И TRUE если и $i, и $y TRUE.
$i || $y Логическое ИЛИ TRUE если или $i, или $y TRUE.

Логическое ИЛИ (OR и ||)

Оператор логическое ИЛИ обозначается как OR или ||. Он выполняет операцию «логическое ИЛИ» над двумя операндами. Если один или оба операнда имеют истинное значение, он возвращает true. Если оба операнда имеют ложные значения, он возвращает false. У вас вероятно возник вопрос, зачем же сделали два варианта одного оператора? Смысл двух разных вариантов оператора «логическое ИЛИ» в том, что они работают с различными приоритетами.

Сначала разберем как работает оператор ||. И так, если один или оба его операнда имеют истинное значение, он возвращает true. Если оба операнда возвращают ложные значения, он вернет false.

Оператор OR работает также как и оператор || за одним исключением, если оператор OR используется с присваиванием, то сначала он вычислит и вернет значение левого операнда, в остальном он работает точно также как и оператор ||, т.е. если один или оба его операнда имеют истинное значение, он возвращает true. Если оба операнда возвращают ложные значения, он вернёт false.

Чтобы стало понятнее, как они работают, приведем следующий пример:

<?php

  // Оператор "||" имеет больший приоритет, чем "or"

  // Результат выражения (false || true) будет присвоен переменной $var1
  // Действие приоритета: $var1 = (false || true)
  $var1 = false || true;

  echo $var1; // => 1

  // Сначала переменной присваивается значение false, а затем вычисляется второй операнд
  // Действие приоритета: ($var2 = false) or true
  $var2 = false or true;  

  echo $var2;  // false не выводится

  // ($var3 = 0) or 3
  $var3 = 0 or 3; 

  echo "<br>$var3";   // => 0

?>

Любые операторы сравнения и логические можно комбинировать в более сложные конструкции:

<?php

  $a = (6 == 6) || (4 <= 9);

  // или так
  echo ('c' != 'd') or ('A' === 'A');

?>

Стоит упомянуть еще об одном важном моменте, касательно обоих операторов OR и ||. Оператор «логическое ИЛИ» начинает свои вычисления со своего левого операнда, если он возвращает true, то правый операнд вычисляться не будет. Это позволяет экономить время исполнения, но нужно внимательно следить за тем, чтобы код, от которого может зависеть корректная работа программы, не был помещен в правый операнд.

Логическое И (AND и &&)

Оператор логическое И обозначается как AND или &&. Он выполняет операцию «логическое И» над двумя операндами. Он возвращает true тогда и только тогда, когда оба операнда имеют значение true. Если один или оба операнда возвращают значение false, оператор возвращает false. Смысл двух разных вариантов записи оператора «логическое И» такой же как и у двух предыдущих операторов, а именно в том, что они работают с различными приоритетами.

Сначала разберем как работает оператор &&. И так, если оба его операнда имеют истинное значение, он возвращает true. Если хотя бы один или оба его операнда возвращают значение false, он тоже вернет false.

Оператор AND работает также как и оператор && за одним исключением, если оператор AND используется с присваиванием, то сначала он вычислит и вернёт значение левого операнда, в остальном он работает точно также как и оператор &&. Если хотя бы один из его операндов возвращает значение false, он тоже вернет false, также если оба операнда возвращают ложные значения, он возвращает false.

Для понимания рассмотрим теперь, как это работает на практике:

<?php

  // Оператор "&&" имеет больший приоритет, чем "and"

  // Результат выражения (true && false) будет присвоен переменной $bar1
  // Действие приоритета: $bar1 = (true && false)
  $bar1 = true && false;


  // Сначала переменной присваивается значение true, а затем вычисляется второй операнд
  // Действие приоритета: ($bar2 = true) and false
  $bar2 = true and false;  

  var_dump($bar1, $bar2);

  // ($bar3 = 9) and 3
  $bar3 = 9 and 3; 

  echo "<br>$bar3";   // => 9

?>

Исключающее ИЛИ (XOR)

Оператор исключающее ИЛИ обозначается как XOR. Он возвращает значение true, если один и только один из операндов имеет значение true. Если оба операнда имеют значение true, оператор вернет значение false.

Так как приоритет оператора XOR такой же как и у операторов AND и OR (ниже чем у оператора присваивания), и он используется в выражении с присваиванием, то сначала он вычисляет и возвращает значение левого операнда.

<?php
 
  // ($a1 = 19) xor 5 > 6 
  $a1 = 19 xor 5 > 6; 		
 
  var_dump($a1);                    // => 19
  var_dump(true xor true);          // false
  var_dump((2 < 3) xor (5 != 5));   // true

?>

Логическое НЕ (!)

Оператор логическое НЕ, его также называют отрицание обозначается знаком !. Он является унарным оператором, помещаемым перед одиночным операндом. Оператор «логическое НЕ» используется для инверсии логического значения своего операнда и всегда возвращает true или false.

Если потребуется инвертировать значение выражения, например a && b, необходимо будет использовать круглые скобки: !(a && b). Также с помощью оператора ! можно преобразовать любое значение x в его логический эквивалент, дважды применив оператор: !!x.

<?php
 
  $a1 = 10;
 
  var_dump((11 == 11));   // true
  
  // оператора ! инвертирует значение
  var_dump(!(11 == 11));  // false
  
  // преобразует в логическое значение
  var_dump(!!$a1);      // true

?>

Понравилась статья? Поделить с друзьями:
  • Мирвазо дерм гель инструкция по применению отзывы пациентов
  • Терморегулятор климат комфорт инструкция по эксплуатации
  • Скачать руководство по ремонту соренто 2010
  • Naprorex 500 mg инструкция на русском
  • Энтеросгель при ротовирусе у взрослых инструкция