Los operadores sobre bits permiten manipular los bits en un entero.
Ejemplo | Nombre | Resultado |
---|---|---|
$a & $b |
And (Y) | Los bits posicionados a 1 en $a Y en $b son posicionados a 1. |
$a | $b |
Or (O) | Los bits posicionados a 1 en $a O $b son posicionados a 1. |
$a ^ $b |
Xor (o exclusivo) | Los bits posicionados a 1 en $a O en $b pero no en los dos son posicionados a 1. |
~ $a |
Not (No) | Los bits que están posicionados a 1 en $a son posicionados a 0, y viceversa. |
$a << $b |
Desplazamiento a la izquierda | Desplaza los bits de $a, $b veces a la izquierda (cada desplazamiento equivale a una multiplicación por 2). |
$a >> $b |
Desplazamiento a la derecha | Desplaza los bits de $a, $b veces a la derecha (cada desplazamiento equivale a una división por 2). |
El desplazamiento de bits en PHP es aritmético. Los bits que son desplazados fuera del entero se pierden. Los desplazamientos a la izquierda hacen aparecer ceros a la derecha, mientras que el bit de signo es desplazado a la izquierda, lo que significa que el signo del entero no es preservado. Los desplazamientos a la derecha desplazan también el bit de signo a la derecha, lo que significa que el signo es preservado.
Utilícense paréntesis para asegurarse de que la
precedencia
deseada sea aplicada correctamente. Por ejemplo,
$a & $b == true
aplica primero
la igualdad, y luego el AND lógico, mientras que
($a & $b) == true
aplica primero el
AND lógico, y luego la igualdad.
Si los dos operandos para los operadores &
,
|
y ^
son strings,
entonces la operación será realizada sobre los valores ASCII de los caracteres y el
resultado será un string. En todos los otros casos, los dos operandos serán
convertidos en entero
y el resultado será un entero.
Si el operando para el operador ~
es un string,
la operación será realizada sobre los caracteres ASCII que componen el string y el
resultado será un string. De lo contrario, el operando y el resultado serán tratados como enteros.
Los operandos y el resultado de los operadores <<
y
>>
son tratados como enteros.
El informe de errores de PHP utiliza campos de bits,
que son una ilustración de la extinción de bits.
Para mostrar los errores, excepto las notificaciones, las
instrucciones del php.ini son :
E_ALL & ~E_NOTICE
Esto se comprende comparando con E_ALL :
00000000000000000111011111111111
Luego, apagando el valor de E_NOTICE...
00000000000000000000000000001000
... y invirtiéndolo a través de ~
:
11111111111111111111111111110111
Finalmente, se utiliza el AND lógico (&) para leer los bits activados
en las dos valores :
00000000000000000111011111110111
Otro medio de llegar a este resultado es utilizar
el OU exclusivo (^
), que busca
los bits que están activados solo en una de las
dos valores, exclusivamente :
E_ALL ^ E_NOTICE
error_reporting también puede ser utilizado para
ilustrar la activación de bits. Para mostrar
únicamente los errores y los errores recuperables,
se utiliza :
E_ERROR | E_RECOVERABLE_ERROR
Este enfoque combina E_ERROR
00000000000000000000000000000001
y E_RECOVERABLE_ERROR
00000000000000000001000000000000
Con el operador OR (|
) para asegurarse de
que los bits están activados en una de las dos valores :
00000000000000000001000000000001
Ejemplo #1 Operaciones sobre bits y enteros
<?php
/*
* Ignórese esta parte,
* es solo formato para clarificar los resultados
*/
$format = '(%1$2d = %1$04b) = (%2$2d = %2$04b)'
. ' %3$s (%4$2d = %4$04b)' . "\n";
echo <<<EOH
--------- --------- -- ---------
resultado valor prueba
--------- --------- -- ---------
EOH;
/*
* Aquí están los ejemplos
*/
$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);
}
?>
El resultado del ejemplo sería:
--------- --------- -- --------- resultado valor prueba --------- --------- -- --------- 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)
Ejemplo #2 Operación sobre bits y strings
<?php
echo 12 ^ 9, PHP_EOL; // Muestra '5'
echo "12" ^ "9", PHP_EOL; // Muestra el carácter de borrado (ascii 8)
// ('1' (ascii 49)) ^ ('9' (ascii 57)) = #8
echo "hallo" ^ "hello", PHP_EOL; // Muestra los valores ASCII #0 #4 #0 #0 #0
// 'a' ^ 'e' = #4
echo 2 ^ "3", PHP_EOL; // Muestra 1
// 2 ^ ((int) "3") == 1
echo "2" ^ 3, PHP_EOL; // Muestra 1
// ((int) "2") ^ 3 == 1
?>
Ejemplo #3 Desplazamiento de bits sobre enteros
<?php
/*
* Aquí están algunos ejemplos
*/
echo "\n--- Desplazamientos a la derecha sobre enteros positivos ---\n";
$val = 4;
$places = 1;
$res = $val >> $places;
p($res, $val, '>>', $places, 'copia del bit de signo ahora a la izquierda');
$val = 4;
$places = 2;
$res = $val >> $places;
p($res, $val, '>>', $places);
$val = 4;
$places = 3;
$res = $val >> $places;
p($res, $val, '>>', $places, 'bits salieron por la derecha');
$val = 4;
$places = 4;
$res = $val >> $places;
p($res, $val, '>>', $places, 'mismo resultado que arriba: no hay desplazamiento más allá de 0');
echo "\n--- Desplazamientos a la derecha sobre enteros negativos ---\n";
$val = -4;
$places = 1;
$res = $val >> $places;
p($res, $val, '>>', $places, 'copia del bit de signo ahora a la izquierda');
$val = -4;
$places = 2;
$res = $val >> $places;
p($res, $val, '>>', $places, 'bits salieron por la derecha');
$val = -4;
$places = 3;
$res = $val >> $places;
p($res, $val, '>>', $places, 'mismo resultado que arriba: no hay desplazamiento más allá de -1');
echo "\n--- Desplazamientos a la izquierda sobre enteros positivos ---\n";
$val = 4;
$places = 1;
$res = $val << $places;
p($res, $val, '<<', $places, 'complemento de ceros a la derecha');
$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, 'el bit de signo salió');
$val = 4;
$places = (PHP_INT_SIZE * 8) - 2;
$res = $val << $places;
p($res, $val, '<<', $places, 'bits salieron a la izquierda');
echo "\n--- Desplazamientos a la izquierda sobre enteros negativos ---\n";
$val = -4;
$places = 1;
$res = $val << $places;
p($res, $val, '<<', $places, 'complemento de ceros a la derecha');
$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 salieron a la izquierda, incluyendo el bit de signo');
/*
* Ignórese esta sección
* Contiene código para el formato de este ejemplo
*/
function p($res, $val, $op, $places, $note = '') {
$format = '%0' . (PHP_INT_SIZE * 8) . "b\n";
printf("Expresión : %d = %d %s %d\n", $res, $val, $op, $places);
echo " Decimal :\n";
printf(" val=%d\n", $val);
printf(" res=%d\n", $res);
echo " Binario :\n";
printf(' val=' . $format, $val);
printf(' res=' . $format, $res);
if ($note) {
echo " Nota : $note\n";
}
echo "\n\n";
}
?>
El resultado del ejemplo en equipos de 32 bit sería:
--- Desplazamientos a la derecha sobre enteros positivos --- Expresión : 2 = 4 >> 1 Decimal : val=4 res=2 Binario : val=00000000000000000000000000000100 res=00000000000000000000000000000010 Nota : copia del bit de signo ahora a la izquierda Expresión : 1 = 4 >> 2 Decimal : val=4 res=1 Binario : val=00000000000000000000000000000100 res=00000000000000000000000000000001 Expresión : 0 = 4 >> 3 Decimal : val=4 res=0 Binario : val=00000000000000000000000000000100 res=00000000000000000000000000000000 Nota : bits salieron por la derecha Expresión : 0 = 4 >> 4 Decimal : val=4 res=0 Binario : val=00000000000000000000000000000100 res=00000000000000000000000000000000 Nota : mismo resultado que arriba: no hay desplazamiento más allá de 0 --- Desplazamientos a la derecha sobre enteros negativos --- Expresión : -2 = -4 >> 1 Decimal : val=-4 res=-2 Binario : val=11111111111111111111111111111100 res=11111111111111111111111111111110 Nota : copia del bit de signo a la izquierda Expresión : -1 = -4 >> 2 Decimal : val=-4 res=-1 Binario : val=11111111111111111111111111111100 res=11111111111111111111111111111111 Nota : bits salieron por la derecha Expresión : -1 = -4 >> 3 Decimal : val=-4 res=-1 Binario : val=11111111111111111111111111111100 res=11111111111111111111111111111111 Nota : mismo resultado que arriba: no hay desplazamiento más allá de -1 --- Desplazamientos a la izquierda sobre enteros positivos --- Expresión : 8 = 4 << 1 Decimal : val=4 res=8 Binario : val=00000000000000000000000000000100 res=00000000000000000000000000001000 Nota : complemento de ceros a la derecha Expresión : 1073741824 = 4 << 28 Decimal : val=4 res=1073741824 Binario : val=00000000000000000000000000000100 res=01000000000000000000000000000000 Expresión : -2147483648 = 4 << 29 Decimal : val=4 res=-2147483648 Binario : val=00000000000000000000000000000100 res=10000000000000000000000000000000 Nota : el bit de signo salió Expresión : 0 = 4 << 30 Decimal : val=4 res=0 Binario : val=00000000000000000000000000000100 res=00000000000000000000000000000000 Nota : bits salieron a la izquierda --- Desplazamientos a la izquierda sobre enteros negativos --- Expresión : -8 = -4 << 1 Decimal : val=-4 res=-8 Binario : val=11111111111111111111111111111100 res=11111111111111111111111111111000 Nota : complemento de ceros a la derecha Expresión : -2147483648 = -4 << 29 Decimal : val=-4 res=-2147483648 Binario : val=11111111111111111111111111111100 res=10000000000000000000000000000000 Expresión : 0 = -4 << 30 Decimal : val=-4 res=0 Binario : val=11111111111111111111111111111100 res=00000000000000000000000000000000 Nota : bits salieron a la izquierda, incluyendo el bit de signo
El resultado del ejemplo en equipos de 64 bit sería:
--- Desplazamientos a la derecha sobre enteros positivos --- Expresión : 2 = 4 >> 1 Decimal : val=4 res=2 Binario : val=0000000000000000000000000000000000000000000000000000000000000100 res=0000000000000000000000000000000000000000000000000000000000000010 Nota : copia del bit de signo ahora a la izquierda Expresión : 1 = 4 >> 2 Decimal : val=4 res=1 Binario : val=0000000000000000000000000000000000000000000000000000000000000100 res=0000000000000000000000000000000000000000000000000000000000000001 Expresión : 0 = 4 >> 3 Decimal : val=4 res=0 Binario : val=0000000000000000000000000000000000000000000000000000000000000100 res=0000000000000000000000000000000000000000000000000000000000000000 Nota : bits salieron por la derecha Expresión : 0 = 4 >> 4 Decimal : val=4 res=0 Binario : val=0000000000000000000000000000000000000000000000000000000000000100 res=0000000000000000000000000000000000000000000000000000000000000000 Nota : mismo resultado que arriba: no hay desplazamiento más allá de 0 --- Desplazamientos a la derecha sobre enteros negativos --- Expresión : -2 = -4 >> 1 Decimal : val=-4 res=-2 Binario : val=1111111111111111111111111111111111111111111111111111111111111100 res=1111111111111111111111111111111111111111111111111111111111111110 Nota : copia del bit de signo ahora a la izquierda Expresión : -1 = -4 >> 2 Decimal : val=-4 res=-1 Binario : val=1111111111111111111111111111111111111111111111111111111111111100 res=1111111111111111111111111111111111111111111111111111111111111111 Nota : bits salieron por la derecha Expresión : -1 = -4 >> 3 Decimal : val=-4 res=-1 Binario : val=1111111111111111111111111111111111111111111111111111111111111100 res=1111111111111111111111111111111111111111111111111111111111111111 Nota : mismo resultado que arriba: no hay desplazamiento más allá de -1 --- Desplazamiento a la izquierda sobre enteros negativos --- Expresión : 8 = 4 << 1 Decimal : val=4 res=8 Binario : val=0000000000000000000000000000000000000000000000000000000000000100 res=0000000000000000000000000000000000000000000000000000000000001000 Nota : complemento de ceros a la derecha Expresión : 4611686018427387904 = 4 << 60 Decimal : val=4 res=4611686018427387904 Binario : val=0000000000000000000000000000000000000000000000000000000000000100 res=0100000000000000000000000000000000000000000000000000000000000000 Expresión : -9223372036854775808 = 4 << 61 Decimal : val=4 res=-9223372036854775808 Binario : val=0000000000000000000000000000000000000000000000000000000000000100 res=1000000000000000000000000000000000000000000000000000000000000000 Nota : el bit de signo salió Expresión : 0 = 4 << 62 Decimal : val=4 res=0 Binario : val=0000000000000000000000000000000000000000000000000000000000000100 res=0000000000000000000000000000000000000000000000000000000000000000 Nota : bits salieron a la izquierda --- Desplazamiento a la izquierda sobre enteros negativos --- Expresión : -8 = -4 << 1 Decimal : val=-4 res=-8 Binario : val=1111111111111111111111111111111111111111111111111111111111111100 res=1111111111111111111111111111111111111111111111111111111111111000 Nota : complemento de ceros a la derecha Expresión : -9223372036854775808 = -4 << 61 Decimal : val=-4 res=-9223372036854775808 Binario : val=1111111111111111111111111111111111111111111111111111111111111100 res=1000000000000000000000000000000000000000000000000000000000000000 Expresión : 0 = -4 << 62 Decimal : val=-4 res=0 Binario : val=1111111111111111111111111111111111111111111111111111111111111100 res=0000000000000000000000000000000000000000000000000000000000000000 Nota : bits salieron a la izquierda, incluyendo el bit de signo
Úsense las funciones de la extensión gmp
para las manipulaciones sobre bits, cuando los enteros exceden
PHP_INT_MAX
.