📌 В мире PHP эти операции встречаются редко, однако в статьях, книгах, либках и других источниках легко можно встретить запись типа:
~
$memory = memory_get_usage() >> 20;
И тут наступает ступор, что за ">>"? Лезешь в доку а там $a >> $b — Сдвиг вправо. Все биты переменной $a сдвигаются на $b позиций вправо (каждая позиция подразумевает "деление на 2").❓ Чё сдвигается, куда? Зачем вообще оно надо? Давайте разбираться.
Думаю многие знают, что число в двоичной (бинарной) системе исчисления представляет собой набор нулей и единиц. Например число 6 будет представлено как 00000110.
👍 Побитовый сдвиг в PHP - это арифметическая операция. Биты, сдвинутые за границы числа, отбрасываются. Сдвиг влево дополняет число нулями справа, сдвигая в то же время знаковый бит числа влево, что означает что знак операнда не сохраняется. Сдвиг вправо сохраняет копию сдвинутого знакового бита слева, что означает что знак операнда сохраняется.
Возвращаемся к нашему оператору
>> $n = 6; // 00000110👉 Здесь четко видно, что мы отбросили самый правый бит, а слева дополнили нулём. Соответственно запись 00000011 в двоичном представлении равна 3 в десятичном. То есть фактически сдвинув один бит — мы поделили на 2, а если сдвинем на 2 бита, то еще раз поделим на 2 (то есть на 4), на 3 бита — получится что на 8.
$k = $n >> 1; // 00000011
❗️ Стоп. Да это же степени двойки!
Возвращаясь к нашему первому примеру
>> 20, получится, что мы делим наше исходное значение на 2 в степени 20. Легко запомнить, что 2^10 = 1024. Тогда: $memory = memory_get_usage() / (1024 * 1024);Так как функция
memory_get_usage() возвращает значение в байтах, то мы всего-лишь перевели всё в Мб. Получается достаточно удобно:>> 10 приводит в КбВ то время как сдвиг вправо означает деление, то сдвиг влево — умножение.
>> 20 приводит в Мб
>> 30 приводит в Гб
$y = 5; // 000000101
echo $y << 2; // 000010100 (5 * 4 = 20)
❤️ Однако, самое вкусное использование побитовых операций заключается не в умножении и делении, а именно в использовании побитовой маски, например для разграничений прав доступа, или других подобных операций:define('U_READ', 1 << 0); // 0001
define('U_CREATE', 1 << 1); // 0010
define('U_EDIT', 1 << 2); // 0100
define('U_DELETE', 1 << 3); // 1000
define('U_ALL', U_READ | U_CREATE | U_EDIT | U_DELETE); // 1111
Выглядит интересно, но об этом и других битовых операциях мы поговорим в следующей части :)#php #junior #source