Bitwise Operators
Оновлено: 09.05.2023
Порозрядні оператори дозволяють обчислювати та маніпулювати окремими бітами в межах цілого числа.
$a & $b
$a | $b
$a ^ $b
~ $a
$a << $b
$a >> $b
Зсув бітів у PHP - це арифметична операція. Біти, зсунуті з обох кінців, відкидаються. При зсуві вліво нулі зсуваються вправо, а знаковий біт зсувається вліво, тобто знак операнда не зберігається. При зсуві вправо копії знакових бітів зсуваються вліво, тобто знак операнда зберігається.
Використовуйте круглі дужки, щоб забезпечити потрібний пріоритет. Наприклад, $a & $b == true обчислює еквівалентність, а потім побітове і; while ($a & $b) == true обчислює побітове і, а потім еквівалентність.
Якщо обидва операнди для операторів &, | і ^ є рядками, то операція буде виконана над ASCII-значеннями символів, що входять до складу рядків, і результатом буде рядок. У всіх інших випадках обидва операнди будуть перетворені в цілі числа і результатом буде ціле число.
Якщо операндом для оператора ~ є рядок, операція буде виконана над ASCII значеннями символів, що складають рядок, і результатом буде рядок, інакше операнд і результат будуть розглядатися як цілі числа.
Операнди і результат для операторів << і >> завжди вважаються цілими числами.
Приклад #1 Порозрядні операції AND, OR та XOR над цілими числами
<?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);
}
?>
Вищенаведений приклад виведе:
Приклад #2 Порозрядні операції XOR над рядками
<?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
?>
Приклад #3 Зсув бітів на цілих числах
<?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) . "b\n";
printf("Expression: %d = %d %s %d\n", $res, $val, $op, $places);
echo " Decimal:\n";
printf(" val=%d\n", $val);
printf(" res=%d\n", $res);
echo " Binary:\n";
printf(' val=' . $format, $val);
printf(' res=' . $format, $res);
if ($note) {
echo " NOTE: $note\n";
}
echo "\n";
}
?>
Вивід вищенаведеного прикладу на 32-бітних машинах:
Вивід вищенаведеного прикладу на 64-бітних машинах:
Використовуйте функції з розширення gmp для побітової маніпуляції з числами, що перевищують PHP_INT_MAX.
pack() розпакувати() gmp_and() gmp_or() gmp_xor() gmp_testbit() gmp_clrbit()