Инструменты пользователя

Инструменты сайта


pobitovye_ili_porazrjadnye_operacii

Различия

Здесь показаны различия между двумя версиями данной страницы.

Ссылка на это сравнение

pobitovye_ili_porazrjadnye_operacii [2018/08/30 03:03] (текущий)
Строка 1: Строка 1:
 +====== Побитовые или поразрядные операции ======
 +  * [[Системы исчисления]]:​ двоичная,​ восьмеричная,​ десятичная,​ шестнадцатеричная.
 +
 +Операнды поразрядных операций могут быть любого целого типа.
 +К побитовым,​ или поразрядным операциям относятся:​
 +  * операция поразрядного И (побитовое умножение) &;
 +  * операция поразрядного ИЛИ (побитовое сложение) |;
 +  * операция поразрядного исключающего ИЛИ ^;
 +  * унарная операция поразрядного отрицания (дополнение) ~.
 +
 +Кроме того, рассматриваются операции сдвигов **<<, >>**.
 +
 +<​note>​Бит установлен,​ значит равен 1. Бит сброшен,​ значит равен 0. Побитовая математика сводится к трем операциям:​ установить бит, сбросить бит и проверить установлен ли бит.</​note>​
 +<​file>​
 +Значение бита(10 -ая система):​128 ​  ​16 ​     1
 +Номер бита: ​                  7 6 5 4 3 2 1 0
 +Значение бита(2 -ая система):​ 1 0 0 1 0 0 0 1 = 145 
 +</​file>​
 +  * Проверить,​ что бит 2 в четвертой степени установлен<​file>​
 +if (x&​16==16)
 +</​file>​
 +  * Стереть бит 2 в четвертой степени. Для этого нужно умножить 10010001 на число 11101111 = 10000001
 +  * Установить бит
 +====== Значение старшего,​ младшего слова(2 байта),​ бита ======
 +  * [[wpru>​Порядок байтов]]
 +Запись многобайтового числа из памяти компьютера в файл или передача по сети требует соблюдения соглашений о том, какой из байтов является старшим,​ а какой младшим. Прямая запись ячеек памяти приводит к возможным проблемам при переносе приложения с платформы на платформу. **Варианты записи**:​ //от старшего к младшему или (англ. big-endian, дословно:​ «тупоконечный»)://​ этот порядок является стандартным для протоколов TCP/IP, он используется в заголовках пакетов данных и во многих протоколах более высокого уровня,​ разработанных для использования поверх TCP/IP. Поэтому,​ порядок байтов от старшего к младшему часто называют сетевым порядком байтов (англ. network byte order). //От младшего к старшему или (англ. little-endian,​ дословно:​ «остроконечный»)//:​ запись начинается с младшего и заканчивается старшим. Этот порядок записи принят в памяти персональных компьютеров с x86-процессорами,​ в связи с чем иногда его называют интеловский порядок байтов.
 +
 +Чтобы получить значение младщего слова (OWORD)
 +
 +(HIWORD)
 +
 +
 +  * **Старший бит**. Старший бит - это самый левый бит для данной разрядности(x16 - 16-ый, x64 - 64-ый). Если число со знаком,​ то для старший бит будет означать знак числа, 1 - отрицательное число, 0 - положительное число.
 +Считать старшим битом самую левую единицу - ошибочно,​ в противном случае в системе со знаком все числа будут или нулем, или отрицательными числами.
 +
 +Мы знаем, что считать можно до бесконечности,​ а потому при записи числа на листочке количество знаков может быть неограниченным. Понятие "​старший"​ возникает только тогда, когда есть некоторое ограничение на количество записываемых символов (разрядов). Поэтому старший бит - это самый левый бит в записи N-битного числа, содержащей N разрядов (которые при необходимости слева добираются нулями). Просто глядя на число нельзя сказать,​ какой бит у него старший,​ нужно ещё знать, во сколько разрядов мы его хотим записать. Т.е. если мы число 128 записываем в переменную типа unsigned char (8 бит), то cтаршим битом будет единица,​ а если записываем в unsigned int (16 или 32 бита в зависимости от платформы),​ то старшим битом будет 0.
 +
 +В случае знакового представления самый старший бит является знаковым (при условии что мы используем запись в дополнительном коде). И именно этот знаковый бит называют старшим (потому что больше нечего назвать этим термином). Вообще,​ старший бит - это крайний бит некоего абстрактного регистра (ограниченной длины) для хранения числа.
 +====== Операции ======
 +  * **Инверсия битов** (поразрядное отрицание,​ дополнение до единицы) инвертирует биты, т.е. каждый бит со значением 1 получает значение 0 и наоборот.
 +  *** Битовое "​И"​** сравнивает последовательно разряд за разрядом два операнда. Для каждого разряда результат равен 1, тогда и только тогда, когда оба соответствующих разряда операндов равны 1. Так, например, ​
 +<​file>​
 +10010011 & 00111101 = 00010001
 +</​file>​потому что только нулевой и четвертый разряды обоих операндов содержат 1. 
 +  * **Битовое "​ИЛИ"​** сравнивает последовательно разряд за разрядом два своих операндов. Для каждого разряда результат равен 1 тогда и только тогда, когда любой из соответствующих разрядов операндов равны 1. Так, например, ​
 +<​file>​
 +10010011 | 00111101 = 10111111
 +</​file>​
 +потому что все разряды (кроме шестого) в одном из двух операндов имеют значение 1. 
 +  * Битовое исключающее "​ИЛИ"​ сравнивает последовательно разряд за разрядом два своих операндов. Для каждого разряда результат равен 1, если один из двух (но не оба) соответствующих разрядов операндов равен 1. Так, например,​
 +<​file>​
 +10010011 ^ 00111101 = 10101110
 +</​file> ​
 +Заметим,​ что, поскольку нулевой разряд в обоих операндах имеет значение 1, нулевой разряд результата имеет значение 0. 
 +
 +Описанные выше операции часто используются для установки некоторых битов, причем другие биты остаются неизменными. Они удобны для фильтрации или маскирования битов. ​
 +
 +  * Сдвиг влево сдвигает разряды левого операнда влево на число позиций,​ указанное правым операндом. Освобождающиеся позиции заполняются нулями,​ а разряды,​ сдвигаемые за левый предел левого операнда,​ теряются. Поэтому,​ например, ​
 +<​file>​
 +10001010 << 2  =  00101000 ,​(каждый разряд сдвинулся на две позиции влево).
 +</​file>​
 +Таким образом,​ х<<2 сдвигает х влево на 2 позиции,​ заполняя освобождающиеся позиции нулями (эквивалентно умножению на 4). 
 +
 +Для значений без знака имеем ​
 +<​file>​
 +10001010 ​ >> 2  = 00100010 , (каждый разряд сдвинулся на две позиции).
 +</​file>​
 +Эти две операции выполняют сдвиг, а также эффективное умножение и деление на степени числа 2. 
 +
 +Пример.
 +<​file>​
 +#include <​iostream>​
 +using namespace std;
 +void main (){
 +
 +      int y=02,​x=03,​z=01,​k;​
 +
 +      k = x|y&​z;  ​
 + cout<<​k<<"​ "; ​ /* Операция ​ 1 */
 +
 +      k = x|y&​~z; ​
 + cout<<​k<<"​ "; ​ /* Операция ​ 2 */
 +
 +      k = x^y&~z;
 + cout<<​k<<"​ "; ​ /* Операция ​ 3 */
 +
 +      k = x&​y&&​z;​
 +   cout<<​k<<"​ "; ​ /* Операция ​ 4 */
 +
 +      x = 1;
 + y = -1;
 +
 +      k = !x|x;
 + cout<<​k<<"​ "; ​ /* Операции ​ 5 */
 +
 +      k = -x|x;
 + cout<<​k<<"​ "; ​   /* Операции ​ 6 */
 +
 +      k = x^x;
 + cout<<​k<<"​ "; ​   /* Операции ​ 7 */
 +
 +      x <<= 3;
 + cout<<​x<<"​ "; ​   /* Операции ​ 8 */
 +
 +      y <<= 3;
 + cout<<​y<<"​ "; ​   /* Операции ​ 9 */
 +
 +      y >>= 3;
 + cout<<​y<<"​ "; ​   /* Операции 10 */
 +}
 +Результат работы программы: ​
 +3 3 1 1 1 -1 0 8 -8 -1
 +</​file> ​
 + 
 +<​note>​Целые константы,​ начинающиеся с цифры 0, являются восьмеричными числами. Восьмеричное представление целых чисел особенно удобно,​ когда приходится работать с поразрядными операциями,​ так как восьмеричные числа легко переводятся в двоичные. В этой задаче числа 01,02,03 соответствуют числам 1, 2 и 3, так что появление восьмеричных чисел служит намеком,​ что программа рассматривает значения x, y и z как последовательности двоичных цифр.</​note> ​
 +Комментарии к коду.
 +  * Операция 1. 
 +<​file>​
 +   x = 03; y = 02; z = 01;
 +   k = x|y&z;
 +Вследствие приоритетов операций:​ k = (x|(y&​z));​. Самое внутреннее выражение вычисляется первым. ​
 +   k = (x|(02&​01));​
 +   02 & 01 = 00000010 & 00000001 = 00000000 = 0
 +   k = (x|00);
 +   03 | 00 = 00000011 | 00000000 = 00000011 = 03
 +   03
 +</​file>​
 +  * Операция 2. 
 +<​file>​
 +   x = 03; y = 02; z = 01;
 +   k = x|y&~z;
 +   k = (x|(y&​(~z)));​
 +
 +   ​~00000001 =  11111110 ​  
 +   02 & 11111110 =  000000010 & 11111110 = 000000010 = 02
 +   03 | 02 = 00000011 | 000000010 = 00000011 = 03
 +   3
 +</​file>​
 +
 +    Операции 3. 
 +<​file>​
 +   x = 03; y = 02; z = 01;
 +   k = x^y&~z;
 + 
 +   k = (03^02);
 +   1
 +</​file>​
 +
 +
 +    Операции 4. 
 +<​file>​
 +   x = 03; y = 02; z = 01;
 +   k = x&​y&&​z;​
 + 
 +   k = ((x&​y)&&​z);​
 +   k = ((03&​02)&&​z);​
 +   k = (02&&​z);​
 +   k = (true&&​z);​
 +   k = (&&​01);​
 +   k = (true&&​true)
 +   true или 1
 +</​file>​
 +
 +Операции 5. 
 +<​file>​
 +   x = 01;
 +   k = !x|x;
 + 
 +   k = ((!x)|x);
 +   k = ((!true)|x);​
 +   k = (false|01);
 +   k = (0|01);
 +   1
 +</​file>​
 +
 +
 +Операции 6. 
 +<​file>​
 +   x = 01;
 +   k = -x|x;
 +
 +   k = ((-x)|x);
 +   k = (-01|01);
 +   -01 | 01  = 11111111 | 00000001 =  11111111 = -1
 +   -1
 +</​file>​
 +<​file>​
 +Операции 7. 
 +   x = 01;
 +   k = x^x;
 + 
 +   k = (01^01);
 +   0
 +</​file>​
 +Операции 8. 
 +<​file>​
 +   x = 01;
 +   x <<= 3;
 + 
 +   x = 01<<​3;​
 +   01 << 3 = 000000001 << 3 =  00001000 = 8
 +   x = 8;
 +   8
 +</​file>​
 +Операции 9. 
 +<​file>​
 +   y = -01;
 +   y <<= 3;
 + 
 +   y = -01<<​3
 +   -01 << 3 = 11111111 << 3 =  11111000 =  -8
 +   y = -8;
 +   -8
 +</​file>​
 +Операции 10. 
 +<​file>​
 +   y = -08;
 +   y >>= 3;
 + 
 +   y = -08>>​3;​
 +   -1
 +</​file>​
 +<​note>​В некоторых случаях вместо -1 может получиться другой результат (8191). Появление этого значения объясняется тем, что на некоторых компьютерах при операции сдвига знак числа может не сохраниться. Не все трансляторы языка C гарантируют,​ что операция сдвига арифметически корректна,​ поэтому в любом случае более ясным способом деления на 8 было бы явное деление y=y/​8.</​note>​
 +
 +====== Побитовые операторы JavaScript ======
 +Для понимания побитовых операторов необходимо свободно уметь работать с двоичным представлением чисел. Если это не так, остается только надеяться,​ что данные операторы не часто вам будут попадаться в вашей практике. Ниже следует перечень побитовых операторов с примерами их применения (примеры и результаты даны, так же, и в бинарной (двоичной) форме): ​
 +
 +Таблица. Побитовые операторы.
 +<​file>​
 +Оператор Название Пример Бин. Результат Бин. ​
 +& Побитовая операция "​И"​ 2&3 0010&​0011 2 0010 
 +| Побитовая операция "​ИЛИ"​ 2|3 0010|0011 3 0011 
 +~ Побитовая операция "​НЕ"​ ~3 ~0011 12 1100 
 +^ Побитовая операция "​ИСКЛЮЧАЮЩЕЕ ИЛИ"​ 2^3 0010^0011 1 0001 
 +<< Побитовая операция "​сдвиг влево"​ 1<<3 0001<<​3 8 1000 
 +>> Побитовая операция "​сдвиг вправо"​ 8>>3 1000>>​3 1 0001
 +</​file> ​
 +
 +Принцип работы побитовых операторов достаточно прост: JavaScript рассматривает последовательно каждый бит операндов,​ выполняет над ними одну из логических операций (исходя из того, что 1 - true, a 0 - false) и формирует бит результата. Исключением являются лишь операции побитового сдвига. Рассмотрим небольшой пример применения побитовых операций - определение четности числа. Если число является четным,​ то его первый (крайний правый) бит равен "​0"​ и операция "&"​ с числом "​1"​ вернет значение "​0"​. Исходя из этого, напишем скрипт: ​
 +
 +Листинг:​ определение четности числа  ​
 +<​file>​
 +var some_number = 105;
 +var result = (some_number & 1) == 0;
 +alert (result);
 +</​file>​
 +Если в результате получится значение false, то заданное число является нечетным,​ в противном случае,​ число является четным. ​
 +
  
pobitovye_ili_porazrjadnye_operacii.txt · Последние изменения: 2018/08/30 03:03 (внешнее изменение)