Операторы сравнения »
« Оператор присваивания
Edit Report a Bug
Побитовые операторы
Побитовые операторы позволяют считывать и устанавливать конкретные биты целых чисел.
| Пример | Название | Результат |
|---|---|---|
| $a & $b | И | Устанавливаются только те биты, которые установлены и в $a, и в $b. |
| $a | $b | Или | Устанавливаются те биты, которые установлены в $a или в $b. |
| $a ^ $b | Исключающее или | Устанавливаются только те биты, которые установлены либо только в $a, либо только в $b, но не в обоих одновременно. |
| ~ $a | Отрицание | Устанавливаются те биты, которые не установлены в $a, и наоборот. |
| $a << $b | Сдвиг влево | Все биты переменной $a сдвигаются на $b позиций влево (каждая позиция подразумевает "умножение на 2") |
| $a >> $b | Сдвиг вправо | Все биты переменной $a сдвигаются на $b позиций вправо (каждая позиция подразумевает "деление на 2") |
Побитовый сдвиг в PHP - это арифметическая операция. Биты, сдвинутые за границы числа, отбрасываются. Сдвиг влево дополняет число нулями справа, сдвигая в то же время знаковый бит числа влево, что означает что знак операнда не сохраняется. Сдвиг вправо сохраняет копию сдвинутого знакового бита слева, что означает что знак операнда сохраняется.
Используйте скобки для обеспечения необходимого приоритета операторов. Например, $a & $b == true сначала проверяет на равенство, а потом выполняет побитовое и; тогда как ($a & $b) == true сначала выполняет побитовое и, а потом выполняет проверку на равенство.
Если оба операдна для &, | и ^ строки, то операция будет производиться с кодами ASCII всех символов строки и в результате вернет строку. Во всех остальных случаях, оба операнда будут преобразованы к целому и результатом будет целое число.
Если операнд для ~ строка, то операция будет производиться с кодами ASCII всех символов строки и в результате вернет строку, в ином случае как операнд, так и результат, будут считаться целыми.
Оба операнда и результат выполнения << и >> всегда считаются за целое.
Опция настроек PHP error_reporting использует побитовые значения, обеспечивая реальную демонстрацию удаления значений битов. Чтобы показать все ошибки, кроме замечаний, инструкции в файле php.ini предлагают использовать: <strong>E_ALL & ~E_NOTICE</strong>
Начинаем со значения E_ALL: 00000000000000000111011111111111 Затем берем значение E_NOTICE... 00000000000000000000000000001000 ... и инвертируем его с помощью <em>~</em>: 11111111111111111111111111110111 Наконец, используем побитовое И (&), чтобы установить только те биты, которые установлены в единицу в обоих значениях: 00000000000000000111011111110111
Другой способ достичь этого - использовать ИСКЛЮЧАЮЩЕЕ ИЛИ (XOR, <em>^</em>), чтобы получить только те биты, которые установлены в единицу либо только в одном, либо только в другом значении: <strong>E_ALL ^ E_NOTICE</strong>
Опция error_reporting также может быть использована для демонстрации установки битов. Показать только ошибки и обрабатываемые ошибки можно следующим образом: <strong>E_ERROR | E_RECOVERABLE_ERROR</strong>
Здесь мы комбинируем E_ERROR 00000000000000000000000000000001 и 00000000000000000001000000000000 с помощью оператора ИЛИ (<em>|</em>), чтобы получить биты, установленные хотя бы в одном операнде: 00000000000000000001000000000001
Пример #1 Побитовыми операции И, ИЛИ и ИСКЛЮЧАЮЩЕЕ ИЛИ (AND, OR и XOR) над целыми числами
/*
* Не обращайте внимания на этот верхний раздел кода,
* это просто форматирование для более ясного вывода.
*/
$format = '(%1$2d = %1$04b) = (%2$2d = %2$04b)'
. ' %3$s (%4$2d = %4$04b)' . "\n";
echo <<<EOH
---------- ----------- - ----------
результат значение оп тест
---------- ----------- - ----------
EOH;
/*
* Вот сами примеры.
*/
$values = array(0, 1, 2, 4, 8);
$test = 1 + 4;
echo "\n Побитовое И (AND) \n";
foreach ($values as $value) {
$result = $value & $test;
printf($format, $result, $value, '&', $test);
}
echo "\n Побитовое (включающее) ИЛИ (OR) \n";
foreach ($values as $value) {
$result = $value | $test;
printf($format, $result, $value, '|', $test);
}
echo "\n Побитовое ИСКЛЮЧАЮЩЕЕ ИЛИ (XOR) \n";
foreach ($values as $value) {
$result = $value ^ $test;
printf($format, $result, $value, '^', $test);
}
Результат выполнения данного примера:
---------- ----------- -- ----------
результат значение оп тест
---------- ----------- -- ----------
Побитовое И (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)
Побитовое (включающее) ИЛИ (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)
Побитовое ИСКЛЮЧАЮЩЕЕ ИЛИ (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)
Пример #2 Побитовая операция ИСКЛЮЧАЮЩЕЕ ИЛИ (XOR) над строками
echo 12 ^ 9; // Выводит '5'
echo "12" ^ "9"; // Выводит символ Backspace (ascii 8)
// ('1' (ascii 49)) ^ ('9' (ascii 57)) = #8
echo "hallo" ^ "hello"; // Выводит ascii-значения #0 #4 #0 #0 #0
// 'a' ^ 'e' = #4
echo 2 ^ "3"; // Выводит 1
// 2 ^ ((int)"3") == 1
echo "2" ^ 3; // Выводит 1
// ((int)"2") ^ 3 == 1
Пример #3 Побитовый сдвиг над целыми числами
/*
* Несколько примеров.
*/
echo "\n--- СДВИГ ВПРАВО НАД ПОЛОЖИТЕЛЬНЫМИ ЦЕЛЫМИ ЧИСЛАМИ ---\n";
$val = 4;
$places = 1;
$res = $val >> $places;
p($res, $val, '>>', $places, 'слева была вставлена копия знакового бита');
$val = 4;
$places = 2;
$res = $val >> $places;
p($res, $val, '>>', $places);
$val = 4;
$places = 3;
$res = $val >> $places;
p($res, $val, '>>', $places, 'биты были выдвинуты за правый край');
$val = 4;
$places = 4;
$res = $val >> $places;
p($res, $val, '>>', $places, 'то же, что и выше; нельзя сдвинуть дальше 0');
echo "\n--- СДВИГ ВПРАВО НАД ОТРИЦАТЕЛЬНЫМИ ЦЕЛЫМИ ЧИСЛАМИ ---\n";
$val = -4;
$places = 1;
$res = $val >> $places;
p($res, $val, '>>', $places, 'слева была вставлена копия знакового бита');
$val = -4;
$places = 2;
$res = $val >> $places;
p($res, $val, '>>', $places, 'биты были выдвинуты за правый край');
$val = -4;
$places = 3;
$res = $val >> $places;
p($res, $val, '>>', $places, 'то же, что и выше; нельзя сдвинуть дальше -1');
echo "\n--- СДВИГ ВЛЕВО НАД ПОЛОЖИТЕЛЬНЫМИ ЦЕЛЫМИ ЧИСЛАМИ ---\n";
$val = 4;
$places = 1;
$res = $val << $places;
p($res, $val, '<<', $places, 'правый край был дополнен нулями');
$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, 'знаковые биты были выдвинуты');
$val = 4;
$places = (PHP_INT_SIZE * 8) - 2;
$res = $val << $places;
p($res, $val, '<<', $places, 'биты были выдвинуты за левый край');
echo "\n--- СДВИГ ВЛЕВО НАД ОТРИЦАТЕЛЬНЫМИ ЦЕЛЫМИ ЧИСЛАМИ ---\n";
$val = -4;
$places = 1;
$res = $val << $places;
p($res, $val, '<<', $places, 'правый край был дополнен нулями');
$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, 'биты были выдвинуты за левый край, включая знаковый бит');
/*
* Не обращайте внимания на этот нижний раздел кода,
* это просто форматирование для более ясного вывода.
*/
function p($res, $val, $op, $places, $note = '') {
$format = '%0' . (PHP_INT_SIZE * 8) . "b\n";
printf("Выражение: %d = %d %s %d\n", $res, $val, $op, $places);
echo " Десятичный вид:\n";
printf(" val=%d\n", $val);
printf(" res=%d\n", $res);
echo " Двоичный вид:\n";
printf(' val=' . $format, $val);
printf(' res=' . $format, $res);
if ($note) {
echo " ЗАМЕЧАНИЕ: $note\n";
}
echo "\n";
}
Результат выполнения данного примера на 32-битных машинах:
--- СДВИГ ВПРАВО НАД ПОЛОЖИТЕЛЬНЫМИ ЦЕЛЫМИ ЧИСЛАМИ ---
Выражение: 2 = 4 >> 1
Десятичный вид:
val=4
res=2
Двоичный вид:
val=00000000000000000000000000000100
res=00000000000000000000000000000010
ЗАМЕЧАНИЕ: слева была вставлена копия знакового бита
Выражение: 1 = 4 >> 2
Десятичный вид:
val=4
res=1
Двоичный вид:
val=00000000000000000000000000000100
res=00000000000000000000000000000001
Выражение: 0 = 4 >> 3
Десятичный вид:
val=4
res=0
Двоичный вид:
val=00000000000000000000000000000100
res=00000000000000000000000000000000
ЗАМЕЧАНИЕ: биты были выдвинуты за правый край
Выражение: 0 = 4 >> 4
Десятичный вид:
val=4
res=0
Двоичный вид:
val=00000000000000000000000000000100
res=00000000000000000000000000000000
ЗАМЕЧАНИЕ: то же, что и выше; нельзя сдвинуть дальше 0
--- СДВИГ ВПРАВО НА ОТРИЦАТЕЛЬНЫХ ЦЕЛЫХ ЧИСЛАХ ---
Выражение: -2 = -4 >> 1
Десятичный вид:
val=-4
res=-2
Двоичный вид:
val=11111111111111111111111111111100
res=11111111111111111111111111111110
ЗАМЕЧАНИЕ: слева была вставлена копия знакового бита
Выражение: -1 = -4 >> 2
Десятичный вид:
val=-4
res=-1
Двоичный вид:
val=11111111111111111111111111111100
res=11111111111111111111111111111111
ЗАМЕЧАНИЕ: биты были выдвинуты за правый край
Выражение: -1 = -4 >> 3
Десятичный вид:
val=-4
res=-1
Двоичный вид:
val=11111111111111111111111111111100
res=11111111111111111111111111111111
ЗАМЕЧАНИЕ: то же, что и выше; нельзя сдвинуть дальше -1
--- СДВИГ ВЛЕВО НАД ПОЛОЖИТЕЛЬНЫМИ ЦЕЛЫМИ ЧИСЛАМИ ---
Выражение: 8 = 4 << 1
Десятичный вид:
val=4
res=8
Двоичный вид:
val=00000000000000000000000000000100
res=00000000000000000000000000001000
ЗАМЕЧАНИЕ: правый край был дополнен нулями
Выражение: 1073741824 = 4 << 28
Десятичный вид:
val=4
res=1073741824
Двоичный вид:
val=00000000000000000000000000000100
res=01000000000000000000000000000000
Выражение: -2147483648 = 4 << 29
Десятичный вид:
val=4
res=-2147483648
Двоичный вид:
val=00000000000000000000000000000100
res=10000000000000000000000000000000
ЗАМЕЧАНИЕ: знаковые биты были выдвинуты
Выражение: 0 = 4 << 30
Десятичный вид:
val=4
res=0
Двоичный вид:
val=00000000000000000000000000000100
res=00000000000000000000000000000000
ЗАМЕЧАНИЕ: биты были выдвинуты за левый край
--- СДВИГ ВЛЕВО НАД ОТРИЦАТЕЛЬНЫМИ ЦЕЛЫМИ ЧИСЛАМИ ---
Выражение: -8 = -4 << 1
Десятичный вид:
val=-4
res=-8
Двоичный вид:
val=11111111111111111111111111111100
res=11111111111111111111111111111000
ЗАМЕЧАНИЕ: правый край был дополнен нулями
Выражение: -2147483648 = -4 << 29
Десятичный вид:
val=-4
res=-2147483648
Двоичный вид:
val=11111111111111111111111111111100
res=10000000000000000000000000000000
Выражение: 0 = -4 << 30
Десятичный вид:
val=-4
res=0
Двоичный вид:
val=11111111111111111111111111111100
res=00000000000000000000000000000000
ЗАМЕЧАНИЕ: биты были выдвинуты за левый край, включая знаковый битРезультат выполнения данного примера на 64-битных машинах:
--- СДВИГ ВПРАВО НАД ПОЛОЖИТЕЛЬНЫМИ ЦЕЛЫМИ ЧИСЛАМИ ---
Выражение: 2 = 4 >> 1
Десятичный вид:
val=4
res=2
Двоичный вид:
val=0000000000000000000000000000000000000000000000000000000000000100
res=0000000000000000000000000000000000000000000000000000000000000010
ЗАМЕЧАНИЕ: слева была вставлена копия знакового бита
Выражение: 1 = 4 >> 2
Десятичный вид:
val=4
res=1
Двоичный вид:
val=0000000000000000000000000000000000000000000000000000000000000100
res=0000000000000000000000000000000000000000000000000000000000000001
Выражение: 0 = 4 >> 3
Десятичный вид:
val=4
res=0
Двоичный вид:
val=0000000000000000000000000000000000000000000000000000000000000100
res=0000000000000000000000000000000000000000000000000000000000000000
ЗАМЕЧАНИЕ: биты были выдвинуты за правый край
Выражение: 0 = 4 >> 4
Десятичный вид:
val=4
res=0
Двоичный вид:
val=0000000000000000000000000000000000000000000000000000000000000100
res=0000000000000000000000000000000000000000000000000000000000000000
ЗАМЕЧАНИЕ: то же, что и выше; нельзя сдвинуть дальше 0
--- СДВИГ ВПРАВО НАД ОТРИЦАТЕЛЬНЫМИ ЦЕЛЫМИ ЧИСЛАМИ ---
Выражение: -2 = -4 >> 1
Десятичный вид:
val=-4
res=-2
Двоичный вид:
val=1111111111111111111111111111111111111111111111111111111111111100
res=1111111111111111111111111111111111111111111111111111111111111110
ЗАМЕЧАНИЕ: слева была вставлена копия знакового бита
Выражение: -1 = -4 >> 2
Десятичный вид:
val=-4
res=-1
Двоичный вид:
val=1111111111111111111111111111111111111111111111111111111111111100
res=1111111111111111111111111111111111111111111111111111111111111111
ЗАМЕЧАНИЕ: биты были выдвинуты за правый край
Выражение: -1 = -4 >> 3
Десятичный вид:
val=-4
res=-1
Двоичный вид:
val=1111111111111111111111111111111111111111111111111111111111111100
res=1111111111111111111111111111111111111111111111111111111111111111
ЗАМЕЧАНИЕ: то же, что и выше; нельзя сдвинуть дальше -1
--- СДВИГ ВЛЕВО НАД ПОЛОЖИТЕЛЬНЫМИ ЦЕЛЫМИ ЧИСЛАМИ ---
Выражение: 8 = 4 << 1
Десятичный вид:
val=4
res=8
Двоичный вид:
val=0000000000000000000000000000000000000000000000000000000000000100
res=0000000000000000000000000000000000000000000000000000000000001000
ЗАМЕЧАНИЕ: правый край был дополнен нулями
Выражение: 4611686018427387904 = 4 << 60
Десятичный вид:
val=4
res=4611686018427387904
Двоичный вид:
val=0000000000000000000000000000000000000000000000000000000000000100
res=0100000000000000000000000000000000000000000000000000000000000000
Выражение: -9223372036854775808 = 4 << 61
Десятичный вид:
val=4
res=-9223372036854775808
Двоичный вид:
val=0000000000000000000000000000000000000000000000000000000000000100
res=1000000000000000000000000000000000000000000000000000000000000000
ЗАМЕЧАНИЕ: знаковые биты были выдвинуты
Выражение: 0 = 4 << 62
Десятичный вид:
val=4
res=0
Двоичный вид:
val=0000000000000000000000000000000000000000000000000000000000000100
res=0000000000000000000000000000000000000000000000000000000000000000
ЗАМЕЧАНИЕ: биты были выдвинуты за левый край
--- СДВИГ ВЛЕВО НАД ОТРИЦАТЕЛЬНЫМИ ЦЕЛЫМИ ЧИСЛАМИ ---
Выражение: -8 = -4 << 1
Десятичный вид:
val=-4
res=-8
Двоичный вид:
val=1111111111111111111111111111111111111111111111111111111111111100
res=1111111111111111111111111111111111111111111111111111111111111000
ЗАМЕЧАНИЕ: правый край был дополнен нулями
Выражение: -9223372036854775808 = -4 << 61
Десятичный вид:
val=-4
res=-9223372036854775808
Двоичный вид:
val=1111111111111111111111111111111111111111111111111111111111111100
res=1000000000000000000000000000000000000000000000000000000000000000
Выражение: 0 = -4 << 62
Десятичный вид:
val=-4
res=0
Двоичный вид:
val=1111111111111111111111111111111111111111111111111111111111111100
res=0000000000000000000000000000000000000000000000000000000000000000
ЗАМЕЧАНИЕ: биты были выдвинуты за левый край, включая знаковый битВнимание
До PHP 7.0 использование отрицательного побитового сдвига, либо сдвига, превышающегося разрядность операционной системы может привести к неопределенному результату. Другими словами, не сдвигайте больше чем на 31 бит на 32-битных системах и больше чем на 63 бита на 64-битных.
Используйте функции из расширения gmp для побитовых операций над числами, большими чем PHP_INT_MAX.
Смотрите также pack(), unpack(), gmp_and(), gmp_or(), gmp_xor(), gmp_testbit(), gmp_clrbit()
# BitwiseFlag.php
abstract 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;
}
}
}
22
grayda dot NOSPAM at DONTSPAM dot solidinc dot org ¶10 years ago
// 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
5
m0sh at hotmail dot com ¶11 years ago
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;
}
7
zooly at globmi dot com ¶10 years ago
function rotate ( $decimal, $bits) {
$binary = decbin($decimal);
return (
bindec(substr($binary, $bits).substr($binary, 0, $bits))
);
}
// Rotate 124 (1111100) to the left with 1 bits
echo rotate(124, 1);
// = 121 (1111001)
// Rotate 124 (1111100) to the right with 3 bits
echo rotate(124, -3);
// = 79 (1001111)
14
¶14 years ago
// 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)
8
vivekanand dot pathak25 at gmail dot com ¶6 years ago
function 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);
8
Silver ¶10 years ago
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
9
frankemeks77 at yahoo dot com ¶7 years ago
echo 8 << 3; //64
7
zewt at hotmail dot com ¶12 years ago
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);
}
3
Eric Swanson ¶14 years ago
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;
}
3
icy at digitalitcc dot com ¶14 years ago
/*
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);
}
}
1
forlamp at msn dot com ¶11 years ago
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
}
4
ivoras at gmail dot com ¶8 years ago
$foo = "1"; // chr(49)
var_dump($foo << 1); // Output is int(2)
$foo = "!"; // chr(33)
var_dump($foo << 1); // Output is int(0)
2
Tbrendstrup ¶14 years ago
function 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));
1
Core Xii ¶9 years ago
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)
1
Adam ¶9 years ago
if ($x & 2 == 2) {
/* code */
}
1
Anonymous ¶8 years ago
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.';
0
ASchmidt at Anamera dot net ¶2 months ago
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)
0
joey ¶3 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.
0
luis at rosety dot com ¶4 years ago
Example of function using bitwise operations for converting hexadecimal color (usually given as 6 hexadecimal digit string, into separated RGB integers)
<?php
function 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 blue
return array($r>>16, $g>>8, $b); // Shift full right each color from its original position
}
0
J. Ketting ¶5 years ago
function rotate ($decimal, $bits) {
$binary = decbin($decimal);
$binary = str_pad($binary, 32, '0', STR_PAD_LEFT);
return (
bindec(substr($binary, $bits).substr($binary, 0, $bits))
);
}
0
Bob ¶10 years ago
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
0
bartbons at debster.nl ¶11 years ago
function 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);
}
Описание на ru2.php.net
Описание на php.ru