Bitwise Operators

Оновлено: 09.05.2023

Порозрядні оператори дозволяють обчислювати та маніпулювати окремими бітами в межах цілого числа.

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

Зсув бітів у 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()