Содержание

Побитовые или поразрядные операции

Операнды поразрядных операций могут быть любого целого типа. К побитовым, или поразрядным операциям относятся:

Кроме того, рассматриваются операции сдвигов «, ».

Бит установлен, значит равен 1. Бит сброшен, значит равен 0. Побитовая математика сводится к трем операциям: установить бит, сбросить бит и проверить установлен ли бит.
Значение бита(10 -ая система):128   16      1
Номер бита:                   7 6 5 4 3 2 1 0
Значение бита(2 -ая система): 1 0 0 1 0 0 0 1 = 145 

Значение старшего, младшего слова(2 байта), бита

Запись многобайтового числа из памяти компьютера в файл или передача по сети требует соблюдения соглашений о том, какой из байтов является старшим, а какой младшим. Прямая запись ячеек памяти приводит к возможным проблемам при переносе приложения с платформы на платформу. Варианты записи: от старшего к младшему или (англ. big-endian, дословно: «тупоконечный»): этот порядок является стандартным для протоколов TCP/IP, он используется в заголовках пакетов данных и во многих протоколах более высокого уровня, разработанных для использования поверх TCP/IP. Поэтому, порядок байтов от старшего к младшему часто называют сетевым порядком байтов (англ. network byte order). От младшего к старшему или (англ. little-endian, дословно: «остроконечный»): запись начинается с младшего и заканчивается старшим. Этот порядок записи принят в памяти персональных компьютеров с x86-процессорами, в связи с чем иногда его называют интеловский порядок байтов.

Чтобы получить значение младщего слова (OWORD)

(HIWORD)

Считать старшим битом самую левую единицу - ошибочно, в противном случае в системе со знаком все числа будут или нулем, или отрицательными числами.

Мы знаем, что считать можно до бесконечности, а потому при записи числа на листочке количество знаков может быть неограниченным. Понятие "старший" возникает только тогда, когда есть некоторое ограничение на количество записываемых символов (разрядов). Поэтому старший бит - это самый левый бит в записи N-битного числа, содержащей N разрядов (которые при необходимости слева добираются нулями). Просто глядя на число нельзя сказать, какой бит у него старший, нужно ещё знать, во сколько разрядов мы его хотим записать. Т.е. если мы число 128 записываем в переменную типа unsigned char (8 бит), то cтаршим битом будет единица, а если записываем в unsigned int (16 или 32 бита в зависимости от платформы), то старшим битом будет 0.

В случае знакового представления самый старший бит является знаковым (при условии что мы используем запись в дополнительном коде). И именно этот знаковый бит называют старшим (потому что больше нечего назвать этим термином). Вообще, старший бит - это крайний бит некоего абстрактного регистра (ограниченной длины) для хранения числа.

Операции

10010011 & 00111101 = 00010001

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

10010011 | 00111101 = 10111111

потому что все разряды (кроме шестого) в одном из двух операндов имеют значение 1.

10010011 ^ 00111101 = 10101110

Заметим, что, поскольку нулевой разряд в обоих операндах имеет значение 1, нулевой разряд результата имеет значение 0.

Описанные выше операции часто используются для установки некоторых битов, причем другие биты остаются неизменными. Они удобны для фильтрации или маскирования битов.

10001010 << 2  =  00101000 ,(каждый разряд сдвинулся на две позиции влево).

Таким образом, х«2 сдвигает х влево на 2 позиции, заполняя освобождающиеся позиции нулями (эквивалентно умножению на 4).

Для значений без знака имеем

10001010  >> 2  = 00100010 , (каждый разряд сдвинулся на две позиции).

Эти две операции выполняют сдвиг, а также эффективное умножение и деление на степени числа 2.

Пример.

#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
Целые константы, начинающиеся с цифры 0, являются восьмеричными числами. Восьмеричное представление целых чисел особенно удобно, когда приходится работать с поразрядными операциями, так как восьмеричные числа легко переводятся в двоичные. В этой задаче числа 01,02,03 соответствуют числам 1, 2 и 3, так что появление восьмеричных чисел служит намеком, что программа рассматривает значения x, y и z как последовательности двоичных цифр.

Комментарии к коду.

   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
   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
  Операции 3. 
   x = 03; y = 02; z = 01;
   k = x^y&~z;
 
   k = (03^02);
   1
  Операции 4. 
   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

Операции 5.

   x = 01;
   k = !x|x;
 
   k = ((!x)|x);
   k = ((!true)|x);
   k = (false|01);
   k = (0|01);
   1

Операции 6.

   x = 01;
   k = -x|x;

   k = ((-x)|x);
   k = (-01|01);
   -01 | 01  = 11111111 | 00000001 =  11111111 = -1
   -1
Операции 7. 
   x = 01;
   k = x^x;
 
   k = (01^01);
   0

Операции 8.

   x = 01;
   x <<= 3;
 
   x = 01<<3;
   01 << 3 = 000000001 << 3 =  00001000 = 8
   x = 8;
   8

Операции 9.

   y = -01;
   y <<= 3;
 
   y = -01<<3
   -01 << 3 = 11111111 << 3 =  11111000 =  -8
   y = -8;
   -8

Операции 10.

   y = -08;
   y >>= 3;
 
   y = -08>>3;
   -1
В некоторых случаях вместо -1 может получиться другой результат (8191). Появление этого значения объясняется тем, что на некоторых компьютерах при операции сдвига знак числа может не сохраниться. Не все трансляторы языка C гарантируют, что операция сдвига арифметически корректна, поэтому в любом случае более ясным способом деления на 8 было бы явное деление y=y/8.

Побитовые операторы JavaScript

Для понимания побитовых операторов необходимо свободно уметь работать с двоичным представлением чисел. Если это не так, остается только надеяться, что данные операторы не часто вам будут попадаться в вашей практике. Ниже следует перечень побитовых операторов с примерами их применения (примеры и результаты даны, так же, и в бинарной (двоичной) форме):

Таблица. Побитовые операторы.

Оператор Название Пример Бин. Результат Бин. 
& Побитовая операция "И" 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

Принцип работы побитовых операторов достаточно прост: JavaScript рассматривает последовательно каждый бит операндов, выполняет над ними одну из логических операций (исходя из того, что 1 - true, a 0 - false) и формирует бит результата. Исключением являются лишь операции побитового сдвига. Рассмотрим небольшой пример применения побитовых операций - определение четности числа. Если число является четным, то его первый (крайний правый) бит равен "0" и операция "&" с числом "1" вернет значение "0". Исходя из этого, напишем скрипт:

Листинг: определение четности числа

var some_number = 105;
var result = (some_number & 1) == 0;
alert (result);

Если в результате получится значение false, то заданное число является нечетным, в противном случае, число является четным.