Обложка канала

Beer::PHP 🍺

3025 @beerphp

Здесь публикуются короткие заметки о PHP, Linux, Unit Testing, DB, OOP, etc., выдержки из статей, книг, видео, курсов и других материалов. Теперь тебе больше не нужно перерывать тонны информации ;)

Beer::PHP 🍺

5 лет назад
Открыть в
Битовые операции (часть 1, сдвиг влево и вправо) 📌 В мире PHP эти операции встречаются редко, однако в статьях, книгах, либках и других источниках легко можно встретить запись типа: ~ $memory = memory_get_usage() >> 20; И тут наступает ступор, что за ">>"? Лезешь в доку а там $a >> $b — Сдвиг вправо. Все биты переменной $a сдвигаются на $b позиций вправо (каждая позиция подразумевает "деление на 2"). ❓ Чё сдвигается, куда? Зачем вообще оно надо? Давайте разбираться. Думаю многие знают, что число в двоичной (бинарной) системе исчисления представляет собой набор нулей и единиц. Например число 6 будет представлено как 00000110. 👍 Побитовый сдвиг в PHP - это арифметическая операция. Биты, сдвинутые за границы числа, отбрасываются. Сдвиг влево дополняет число нулями справа, сдвигая в то же время знаковый бит числа влево, что означает что знак операнда не сохраняется. Сдвиг вправо сохраняет копию сдвинутого знакового бита слева, что означает что знак операнда сохраняется. Возвращаемся к нашему оператору >>
$n = 6;       // 00000110
$k = $n >> 1; // 00000011

👉 Здесь четко видно, что мы отбросили самый правый бит, а слева дополнили нулём. Соответственно запись 00000011 в двоичном представлении равна 3 в десятичном. То есть фактически сдвинув один бит — мы поделили на 2, а если сдвинем на 2 бита, то еще раз поделим на 2 (то есть на 4), на 3 бита — получится что на 8. ❗️ Стоп. Да это же степени двойки! Возвращаясь к нашему первому примеру >> 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