Operadores bit a bit

Sean las variables PHP:

$a = 18; // 10010 = 0001 0010
$b = 7;  // 00111 = 0000 0111

¿Qué resultado se obtiene al ejecutar estas operaciones?

$aAndB = $a & $b;
$aOrB = $a | $b;
$aXorB = $a ^ $b;
$notA = ~$a;
$aShiftLeft1 = $a << 2;
$aShiftRight2 = $a >> 2;

Solución

#!/bin/php
<script language="php">
$a = 18;
$b = 7;

$aBin = decbin($a);         // 10010 = 0001 0010
$bBin = decbin($b);         // 00111 = 0000 0111
   
$aAndB = $a & $b;           // 00010 ≡ 2
$aOrB = $a | $b;            // 10111 ≡ 1 + 2 + 4 + 16 = 23
$aXorB = $a ^ $b;           // 10101 ≡ 1 + 4 + 16 = 21
$notA = ~$a;                // 0001 0010 inverted is 1110 1101 ≡
                            // ≡ 1 + 4 + 8 + 32 + 64 - 128 = -19
$aShiftLeft1 = $a << 2;     // 18 * 2 * 2 = 72
$aShiftRight2 = $a >> 2;    // 18 / 2 / 2 = 4

$aAndBBin = decbin($aAndB);
$aOrBBin = decbin($aOrB);
$aXorBBin = decbin($aXorB);
$notABin = decbin($notA);

echo "---------------------------------------------------------\r\n";
echo " bitwise operators\r\n";
echo "---------------------------------------------------------\r\n";
echo "$a = $a ≡ 0001 0010\r\n";
echo "$b = $b ≡ 0000 0111\r\n"; 

Echo "$a & $b = $a & $b = $aBin & $bBin = $aAndBBin ≡ $aAndB\r\n";
echO "$a | $b = $a | $b = $aBin | $bBin = $aOrBBin ≡ $aOrB\r\n";
eCHo "$a ^ $b = $a ^ $b = $aBin ^ $bBin = $aXorBBin ≡ $aXorB\r\n";
ECHO "~$a = ~$a = $notA ≡ $notABin\r\n";  

echo "$a << 2 = $a << 2 = $aShiftLeft1\r\n";
echo "$a >> 2 = $a >> 2 = $aShiftRight2";     

Salida del PHP shell script:

jordi-laptop@jordi /cygdrive/c/wamp/www/operators
$ php bitwise.php
---------------------------------------------------------
 bitwise operators
---------------------------------------------------------
$a = 18 = 0001 0010
$b = 7 = 0000 0111
$a & $b = 18 & 7 = 10010 & 111 = 10 ≡ 2
$a | $b = 18 | 7 = 10010 | 111 = 10111 ≡ 23
$a ^ $b = 18 ^ 7 = 10010 ^ 111 = 10101 ≡ 21
~$a = ~18 = -19 ≡ 11111111111111111111111111101101
$a << 2 = 18 << 2 = 72
$a >> 2 = 18 >> 2 = 4

Explicación

Antes de nada, es interesante notar que este script se ejecuta en la línea de comandos. Desde PHP 4.3.0 hay soporte para CLI SAPI.

Observa, por otro lado, que utilizamos esta etiqueta de apertura de PHP (opening PHP tag):

<script language="php">

Lo hacemos por cuestiones puramente didácticas, para repasar la sintaxis de PHP y conocer algunos de sus aspectos menos habituales, sin embargo lo más normal y recomendado es utilizar esta otra:

<?php

La Wikipedia explica bien las operaciones a nivel de bits. Y cómo no, no te olvides consultar el manual de PHP para ver qué dice sobre las operaciones bitwise. A excepción del operador NOT, que es el más complicado de todos, los operadores a nivel de bit son fáciles de entender.

Hay que saber que PHP representa los números binarios negativos en complemento a dos. Para poder seguir esta explicación cómodamente primero deberías saber convertir a mano un número negativo expresado en complemento a dos (two’s complement) a su contraparte decimal.

En Internet está disponible esta herramienta online para pasar números decimales a complemento a dos, y viceversa:

$notA = ~$a;                // 0001 0010 inverted is 1110 1101 ≡
			    // ≡ 1 + 4 + 8 + 32 + 64 - 128 = -19

Ya para terminar, ¿sabías que los nombres de las funciones y los métodos PHP son case-insensitive?:

Echo "$a & $b = $a & $b = $aBin & $bBin = $aAndBBin ≡ $aAndB\r\n";
echO "$a | $b = $a | $b = $aBin | $bBin = $aOrBBin ≡ $aOrB\r\n";
eCHo "$a ^ $b = $a ^ $b = $aBin ^ $bBin = $aXorBBin ≡ $aXorB\r\n";
ECHO "~$a = ~$a = $notA ≡ $notABin\r\n";